How to create a `IN` clause in CakePHP query? - cakephp

How do you make it where in clause in new CakePHP? I'm trying:
$restaurants->find()->where(['id' => $r_ids])->all();
Where $r_ids is array of ids I need in my query, but this doesn't work as expected.

With CakePHP 3.x it's now necessary to either indicate the data type, which for an array of values need to have [] appended to the type:
$query = $articles
->find()
->where(['id' => $ids], ['id' => 'integer[]']);
or to explicitly make use of the IN keyword:
$query = $articles
->find()
->where(['id IN' => $ids]);
See also
Cookbook > Database Access & ORM > Query Builder > Automatically Creating IN Clauses

Try this one for CakePHP 3.x
$query = $restaurants
->find()
->where(['id IN' => $r_ids]);
$query->all();

You can also use the short syntax:
$result = $restaurants->find('all',
['conditions' => ['id IN' =>$r_ids]]
)->all();

In Cakephp 3.x, If you have multiple where conditions then your query will be as below:
return $this
->find()
->contain([
'XYZ.Articles',
'YYY.Managers',
'ZZZ.Readers',
])
->where([
'ID' => $ids,
'READER.STATUS' => $xyz,
],[
'ID' => 'integer[]'
])
;

Related

Cakephp left outer join from query builder is not giving correct sql format

I want to make sql query like this. Which is working fine. but if I am trying with using cakephp query builder I could not find any path. I am also posting what I have done in cakephp query builder. Please check...
$query = '
select
schemes.name,
most_recent_export_product.itc_hs_code,
sum(epinvoicevalueusd) from oc
join (
select
oc_id, itc_hs_code
from
e_products
where
itc_hs_code is not null
group
by oc_id
order
by oc_id, created desc
)
as most_recent_export_product
on oc.id = most_recent_export_product.oc_id
join
schemes on schemes.id = oc.scheme_id
where
application_status_id = 8 AND
certificate_issue_date >= 2022-09-28
group by
scheme_id, most_recent_export_product.itc_hs_code
order by
scheme_id, most_recent_export_product.itc_hs_code';
$connection = ConnectionManager::get('default');
$ocData = $connection->execute($query)->fetchAll('assoc');
In cake php I am using query builder to do the same like
$exdata = $this->EProducts
->find()
->select(['oc_id', 'itc_hs_code'])
->group('oc_id')
->order(['created' => 'DESC']);
$ocData = $this->oc
->find()
->select([
'scheme_name' => 'Schemes.name',
'itc_hs_code' => 'ExportProducts.itc_hs_code',
'epinvoicevalueusd' => 'sum(oc.epinvoicevalueusd)'
])
->join([
'exp' => [
'type' => 'LEFT',
'conditions' => 'exp.oc_id = oc.id',
'group' => 'exp.oc_id'
]
])
->contain('Schemes')
->where([
'application_status_id' => 8,
'certificate_issue_date >=' => '2022-09-28'
])
->group(['scheme_id'])
->order(['scheme_id']);
I dont how to make it with using query builder in cakephp. Please help anyone. :)

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

selecting only desired firleds from query

I have a many to many relation between sizes and toppings and and have a thrird table which contains extra fields the table is named toppings_sizes
Now I want to select only one field from toppings_sizes, at the moment I have a query which delivers all available field in all 3 tables.
$rs = $this->Toppings
->find()
->contain(['Sizes'])
->where(['category_id' => $categoryId]);
debug( json_encode($rs, JSON_PRETTY_PRINT));
I this can I need only 2 fields Sizes.name and ToppingsSizes.price
One way is by adding ->select to specify fields:
$rs = $this->Toppings
->find()
->select(['Sizes.name', 'ToppingsSizes.price'])
->contain(['Sizes'])
->where(['category_id' => $categoryId]);
$rs = $this->Toppings
->find()
->contain([
'Sizes' => function ($q) {
return $q
->select(['name']);
},
'ToppingsSizes' => function ($q) {
return $q
->select(['price']);
}
]);
->where(['category_id' => $categoryId]);
By Using this code you can get desired fields from table.
You need to pass Relationship model names into contain() method array which model entity you need in result data.
$rs = $this->Toppings
->find()
->select(['Sizes.name', 'ToppingsSizes.price'])
->contain(['Sizes','ToppingsSizes'])
->where(['Toppings.category_id' => $categoryId]);

CakePHP 3.2 find first with where

I'm working with CakePHP 3.2. Here is my find query:
$a=$this->A->find('all', ['where' => [ 'b=='=>5, 'c>'=>1000 ]])->first();
// For debuging what I receive:
$data=$a->toArray();
print_r($data);
I'd like to select first record in 'A', whose column 'b' equals 5 and column 'c' is grater than 1000. What am I doing incorrectly? The above query returns all records from 'A' table.
Use conditions instead of where
$a=$this->A->find('all', ['conditions' => ['b'=>5, 'c >'=>1000]])->first();
simply
$a = $this->A->find()
->where([ 'b' => 5, 'c >' => 1000 ])
->first();
debug($a)
you don't need to call toArray() since first already returns a single entity
It should be like this:
$data = $this->A->find()->where(['b' => 5, 'c >' => 1000])->first();
Use conditions instead of where
$query = $articles->find('all', [
'conditions' => ['Articles.title LIKE' => '%Ovens%']
]);
$result = $query->toArray();

Cakephp 3 : How to give condition in get method?

I am trying to give a condition in cakephp 3 get method, where data will fetch by foreign id not primary key. Here I have tried below code:
$eventPasswordAll = $this->EventPasswordAll->get($id, [
'conditions' => ['event_id'=>$id],
'contain' => ['Events']
]);
But it showing me data according to id(primary key), not by event_id. How I add this condition in get methods like where event_id=my get id ?
Don't use get, use find. According to CakePHP 3.0 Table API, the get method:
Returns a single record after finding it by its primary key, if no record is found this method throws an exception.
You need to use find:
$eventPasswordAll = $this->EventPasswordAll->find('all', [ // or 'first'
'conditions' => ['event_id' => $id],
'contain' => ['Events']
]);
// or
$eventPasswordAll = $this->EventPasswordAll->find()
->where(['event_id' => $id])
->contain(['Events']);
Sometimes you want to get the id and the userid..
$this->loadModel('Jobapplications');
$application = $this->Jobapplications->find('all', [
'conditions' => ['id' => $id, 'user_id' => $user_id]
]);
$application = $application->first();

Resources