Error: SQLSTATE[42P01]: Undefined table: "Missing FROM-claouse entry for table - cakephp

Hy I create a join query using cakephp find as shown below :
$test = $this->DiagnosisBind->find(
'all',
[
'table' => 'diagnosis_binds',
'alias' => 'dbinds',
'order' => 'dbinds.set_num ASC',
//'recursive' => 0,
'conditions' => [
'dbinds.deleted IS NULL',
'dbinds.diagnosis_id ='.$diagnosisData[0][0]['id']
],
'joins' => [
[
'type' => 'INNER',
'table' => 'diagnosis_treats',
'alias' => 'dtreats',
'conditions' => [
'dtreats.diagnosis_bind_id = dbinds.id'
]
],
[
'type' => 'INNER',
'table' => 'medical_masters',
'alias' => 'medmas',
'conditions' => [
'medmas.deleted IS NULL'
]
]
],
'fields' => [
'dtreats.id',
'dtreats.medical_name',
'dtreats.amount',
'dbinds.days'
]
]
);
When executing the query, I got this error :
I have read this post missing FROM-clause entry for table "Grupo" cakephp And solution is create a recursive (I have tried but failed) and use containable (I'm not suppose to create containable). So what's wrong in my find above. Thank you
Note:
I'm using cakephp 2.0
Postgresql

There are no table and alias options for query builder finders, they are only available for joins, so your main table will use the default alias as you can see in the query in the error message, and that alias is DiagnosisBind, hence using dbinds will cause an error.
Long story short, use DiagnosisBind instead of dbinds.
Side note, never ever inject data into single value conditions (or in the key of a key => value condition for that matter):
'dbinds.diagnosis_id ='.$diagnosisData[0][0]['id']
That's a possible SQL injection vulnerability!, always use the key => value syntax, or bindings:
'DiagnosisBind.diagnosis_id' => $diagnosisData[0][0]['id']

Related

CakePHP 3.x OR In Find Condition With Multiple Same Fields

I would like to query the database for
Plates.page_number => 1 OR Plates.page_number => Cover
I am attempting to use the following code, but I am not getting the results I am looking for because of a duplicate array key, how can I search the same field for two different values?
$query = $this->Ledgers->find('all', array(
'contain' => array(
'Plates' => [
'conditions' => [
'OR' => [
'Plates.plate_title' => 'Front Cover',
'Plates.page_number' => '1',
'Plates.page_number' => 'Cover' // Duplicate Array Key
]
]
], 'Plates.PlateImages', 'Tribes'
),
'conditions' => array(
'Ledgers.disabled' => 'n', 'Ledgers.id IN' => $ledgerIds
)
))->orderAsc('ledger_title');
Please try wrapping your conditions in separate arrays, eg:
'OR' => [
['Plates.page_number' => '1'],
['Plates.page_number' => 'cover'],
...
]
More info can be found in CakePHP docs:
Query Builder -> Advanced Conditions

CakePHP 3 Sort by associated model with HasOne relationship

Order HasOne Suborder
Suborder BelongsTo Order
I need to sort Orders by a field in Suborders, but sorting by virtual fields appears to have been removed in Cake 3.x
In OrdersTable.php, I have
$this->hasOne('Suborder', [
'className' => 'Suborders',
'foreignKey' => 'order_id',
'strategy' => 'select',
'conditions' => function ($exp, $query) {
return $exp->add(['Suborder.id' => $query
->connection()
->newQuery()
->select(['SSO.id'])
->from(['SSO' => 'suborders'])
->where([
'Suborder.order_id = SSO.order_id',
'SSO.suborder_type_id in' => [1, 2, 3]
])
->order(['SSO.id' => 'DESC'])
->limit(1)]);
}
]);
In OrdersController.php, I have
$this->paginate = [
'limit' => 20,
'order' => ['id' => 'desc'],
'sortWhitelist' => [
'id',
'title',
'client_order',
'substatus',
'Workflows.order_status_id',
'Clients.name',
'ProductTypes.type',
'Suborder.due_date',
'Suborder.created',
],
];
$orders = $this->paginate($collection);
In index.ctp, I have
$this->Paginator->sort('Suborder.created', 'Order Placed'),
$this->Paginator->sort('Suborder.due_date'),
and the error I'm getting is Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Suborder.created' in 'order clause'. How do I get Cake to include the Suborder in the initial query for sorting and pagination?
Edit:
$collection = $this->Orders->find()
->contain([
'Clients',
'CurrentAssignment.Users',
'Workflows.OrderStatuses.Category',
'Workflows.OrderStatuses.Departments' => function ($q) use ($uID) {
return $this->Departments->find()->matching('Users', function ($q) use ($uID) {
return $q->where(['Users.id' => $uID]);
});
},
'ClientProducts.ProductTypes',
'Reviews' => function ($q) {
return $q->where(['review_type_id is not' => 6]);
},
'Reviews.ReviewTypes',
'PublicNotes',
'ActiveReview',
'Suborder',
'Suborder.SuborderTypes',
'Suborders.SuborderTypes',
]);
and $collection is modified with 150 lines of wheres, orWheres, and joins based on a number of conditions.
You have configured the assocaition to use the select strategy, which will use a separate query to retrieve the data (currently wrongly documented), hence you cannot reference it in the main query used for pagination.
So you have to use the default join strategy instead if you want to sort on it.
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together > HasOne Associations

HABTM accessing array value in condition

Hey my problem is to define a condition for a HABTM Model
(int) 0 => array(
'Article' => array(
'id' => '',
'title' => '',
'body' => '',
'created' => null,
'modified' => null
),
'Channel' => array(
'id' => '',
'channelname' => '',
'created' => null,
'modified' => null
),
'Tag' => array(
(int) 0 => array(
'id' => '1',
'value' => 'example',
),
(int) 1 => array(
[maximum depth reached]
),
(int) 2 => array(
[maximum depth reached]
)
),
),
I want to define a condition that searches the Tag values for specific values .. like that:
$this -> Article -> find('all', array('conditions' => array('Tag.0.value' => 'test'))
So does someone knows how to "foreach" that array in this condition? thanks (:
You either need to:
Run your find from the other direction (using CakePHPs awesome Containable Behavior to get the Articles):
$this->Tag->find('all', array(
'conditions' => array(
'Tag.value' => 'test'
),
'contain' => array(
'Article'
)
));
Or, use JOINs. Run your find like you're doing, but do an INNER JOIN on tags where the tag value='test'
You cannot limit the main Model's results based on an associated model's conditions. The reason is, when you rely on recursive, or use Contain, CakePHP actually creates separate queries to pull in your different models' data. Therefore, you can't have a condition in one query affect the other query.
See similar question/answers:
How do I restrict query results based on sub-results in CakePHP?
Conditions in JOINed tables shows error CakePHP
cakephp contain filtering by parent model value
cakephp contain association conditions issue
Adding conditions to Containable in CakePHP

Cakephp pagination with join table field sort is not working

Cakephp pagination with join table sort is not working for join table fields. But for custom sql join query working fine. Please help me to come out.
See below sample code.. I have Artist.name join table field in order.
$this->paginate = array(
'fields' => array(
'id',
'Song.title',
'Song.date',
'Artist.id AS artist_id',
'Artist.name AS artist_name',
'COUNT(SongViews.id) AS views'
),
'group' => array('ArtistsSong.song_id'),
'recursive' => 0,
'limit' => 20,
'joins' => array(
array(
'table' => 'tbl_artists_songs',
'alias' => 'ArtistsSong',
'conditions'=> array('Song.id = ArtistsSong.song_id')
),array(
'table' => 'tbl_artists',
'alias' => 'Artist',
'conditions'=> array('Artist.id = ArtistsSong.artist_id')
),array(
'table' => 'tbl_song_views',
'alias' => 'SongViews',
'type' => 'left',
'conditions'=> array('SongViews.song_id = ArtistsSong.song_id')
),
),
'order' => array('Artist.name'=>'asc')
);
It is a bug in CakePHP.
However, there is a trick to do it.
You should add a virtual field in your primary model.
Assuming your primary model is Song, you should add this before calling paginate:
$this->Song->virtualFields = array(
'artist_name' => 'Artist.name'
);
And now, you can sort by artist_name.
This question was asked nearly 5 years ago, but I came across the same problem in CakePHP 3. I realised I needed to whitelist the field to allow for sorting:
$this->paginate = array(
...
'sortWhitelist' => array ('Artist.name')
);
The Paginator automatically whitelists fields from the original table but not from the JOINed tables.
$this->paginate = ['fields' => ['id', 'name', 'company_id'],
'contain' => [
'Companies' =>
[
'fields' => ['id', 'name'],
'sort'=>['name'=>'ASC']
]
'limit' => 10,
];
Sorting by columns in associated models requires setting sortWhitelist.
$this->paginate['order'] = [ 'Artist.name' => 'desc' ];
$this->paginate['sortWhitelist'] = ['Artist.name', 'Song.title'];
$this->paginate['limit'] = $this->paginate['maxLimit'] = 200;
In HTML you have to set below line in table header:
<?= $this->Paginator->sort('Song.title', __('Title')) ?>

Doing manual joins in CakePHP does not invoke the constructor of the joined model (Virtual Fields needed)

I am trying to build a dynamic query through an array of joined tables. These generate dynamic aliases to avoid conflicts (non unique aliases).
However, in my joined tables - I have some virtualFields which are not getting processed. Upon further inspection, it appears that the joined tables __construct() functions are not getting called.
Is there a way to get virtualFields on a joined table in CakePHP v2.2.8?
Thanks
Manual joins do not use your models
Manual joins do not make use of your models. Using manual joins, you are manually defining a join and giving it an alias. Although this alias may be the same as an existing model, CakePHP will not use your model for the joined tables.
If you need virtualFields, depending on 'what' data is used, you may be able to move the virtualField to the 'main' model you're querying, for example:
$this->Foo->virtualFields['foobar'] = 'CONCAT(\'Hello \', Bar.name)';
$foo = $this->Foo->find(
'all',
array(
'fields' => array(
'Foo.name',
'Foo.foobar',
),
'joins' => array(
array(
'table' => 'bars',
'alias' => 'Bar',
'type' => 'INNER',
'conditions' => array(
'Bar.id = Foo.bar_id',
)
)
),
'recursive' => -1
)
);
debug($foo);
Returns;
array(
(int) 0 => array(
'Foo' => array(
'title' => 'Foo One',
'foobar' => 'Hello World'
)
),
(int) 1 => array(
'Foo' => array(
'title' => 'Foo Two',
'foobar' => 'Hello Planet'
)
),
)

Resources