How to use an isNull expression in an OR condition - cakephp

Cakephp Version: 4.3.5
I'm trying to construct an Or condition that uses an isNull expression in a custom finder.
In text I am trying to do this:
public function findMyTasks(Query $query, array $options): object
{
$query
->where([
'Tasks.status' => $options['status'],
'Tasks.user_id' => $options['user_id'],
'OR' => [
['Tasks.contact_id' => null], // HERE IS THE CONDITION
['Contacts.status' => 1]
],
]);
return $query;
}
If I wanted to use isNull in a condition without OR I would use the following:
->where(function (QueryExpression $exp, Query $q) {
return $exp->isNull('Tasks.contact_id');
})
I have tried various combinations by referencing the advanced condition page here but I cannot combine the expression with the condition without a syntax error.
Question:
How can I construct this finder that uses isNull with an OR condition.
Thanks,
Zenzs.

As documented:
'OR' => [
['Tasks.contact_id IS' => null],
['Contacts.status' => 1]
],
Just a bit further down on that page:
https://book.cakephp.org/4/en/orm/query-builder.html#automatic-is-null-creation

Related

How to get contain clause to generate the correct code in CakePHP

I have the following code in a Table definition.
$paginationQuery = $this->find()
->select([
'Members__id','Members__member_type','Members__first_name',
'Members__middle_name','Members__last_name','Members__suffix'
])
->contain([
'SocialMembers' => [
'foreignKey' => false,
'queryBuilder' => function (Query $q) {
return $q->where([
'Members.Members__id' => 'SocialMembers.full_member_id'
]);
}
]
])
->from([
$this->getAlias() => $query
])
->order([
'Members__last_name' => 'ASC',
'Members__first_name' => 'ASC'
]);
return $paginationQuery;
This is to paginate the results of a union of two sets of extracted data.
The problem comes from the queryBuilder function. The left join that is generated looks like this:
LEFT JOIN members SocialMembers ON (
SocialMembers.member_type = 2
AND Members.Members__id = 'SocialMembers.full_member_id'
)
There is an unneeded pair of single quotes around SocialMembers.full_member_id. queryBuilder appears to correctly handle the Members.Members__id, but not the value field of the array. Is there any way to get this to generate correctly?
Was able to resolve this by moving the contains clause to the preceding finder methods.

Create a query to filter results by multiple data associations with logical disjunction

I'm trying to filter results of a table based on two associated tables using a logical disjunction (OR).
For example I want to find all Products filtering on Reviews and Reviews.Users.
where Reviews.Users.super is ->eq(true)
OR
where Reviews.visibility is ->eq('visibility', 'public') AND Reviews.published is ->isNotNull('published')
using two ->innerJoinWith creates a conjunction.
this->Products->find()
->distinct()
->where(['Products.status' => 'current'])
->contain(['Reviews.Users'])
->innerJoinWith('Reviews', function($q) {
return $q
->where(['Reviews.visibility' => 'public'])
->andWhere(['Reviews.published IS NOT' => null]);
})
->innerJoinWith('Reviews.Users', function($q) {
return $q
->where(['Users.super' => true]);
})
->all();
when trying to use leftJoins as suggested by #ndm I get a
$this->Products->find()
->leftJoinWith('Reviews')
->leftJoinWith('Reviews.Users')
->where([
'OR' => [
'Reviews.Users.super' => true,
'Reviews.visibility' => 'public'
]
])
->andWhere([
'Reviews.published IS NOT' => null
])
Column not found: 1054 Unknown column 'Reviews.Users.super' in 'where clause'

Select Distinc on cakephp 3 return wrong fields

this function should return the field of the table I want, but this doesn't happen, return all field of the table, with simply sql work fine "SELECT DISTINCT especie FROM packages"
public function listSpicies()
{
$packages = $this->Packages->find('all')
->select('especie')
->distinct('especie');
$this->set([
'success' => true,
'data' => $packages,
'_serialize' => ['success', 'data']
]);
}
I think You can use something like this:
$packages = $this->Packages->find('all' , [
'fields' => [
'anyAlias' => 'DISTINCT(espiece)'
]
])
->toArray();
Notice. If this collection is serialized and outputted as a JSON, check \App\Model\Entity\Package - if espiece is inside $_hidden array - remove this from array

CakePHP3: cannot get matching working properly

If I write the following query:
$sites = $this->Sites->find()
->contain(['Agthemes'])
->matching('Agthemes', function ($q) {
return $q->where([
'Agthemes.site_id IS NOT' => null
]);
})
->all();
I only get Sites which have existing Agthemes.
Now I write a similar query but with one additional association level:
$users = $this->Users->find('all')
->contain([
'Sites.Agthemes'
])
->matching('Sites.Agthemes', function ($q) {
return $q->where([
'Agthemes.site_id IS NOT' => null
]);
})
->distinct(['Users.id'])
->limit(5)
->all();
And in that case, I also get Sites with empty Agthemes.
Could you tell me why?
EDIT
I add the relationships
SitesTable
$this->hasMany('Agthemes', [
'dependent' => true,
'cascadeCallbacks' => true,
]);
$this->belongsToMany('Users', [
'joinTable' => 'sites_users',
]);
UsersTable
$this->belongsToMany('Sites', [
'targetForeignKey' => 'site_id',
'joinTable' => 'sites_users',
]);
AgthemesTable
$this->belongsTo('Sites');
In DebugKit, look at the queries being run. Using 'contain' often runs completely separate queries, then combines the results (depends on the association type).
If you want to be sure to limit the results based on conditions against an associated model, use 'joins' instead of 'contain'.
See this page for details about how the associations use (or don't use) joins, and how you can change the join strategy...etc:
https://book.cakephp.org/3.0/en/orm/associations.html

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

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[]'
])
;

Resources