CakePHP find conditions with multiple 'OR' - cakephp

I'm having a real headache getting this to work correctly. This is my desired outcome in raw MySQL:
WHERE `EmailTemplate`.`is_archived` = '0'
AND
((`EmailTemplate`.`project_id` IS NULL) OR (`EmailTemplate`.`project_id` = 101))
AND
((`EmailTemplate`.`user_id` IS NULL) OR (`EmailTemplate`.`user_id` = 44))
How does this translate into a CakePHP conditions array?

Solved this, eventually.
$templateConditions = array(
'EmailTemplate.is_archived' => 0,
'AND' => array(
'OR' => array(
array('EmailTemplate.project_id IS NULL'),
array('EmailTemplate.project_id' => $this->request->data['Project']['project_id'])
)
),
array(
'OR' => array(
array('EmailTemplate.user_id IS NULL'),
array('EmailTemplate.user_id' => $this->Auth->user('id'))
)
)
);

Related

cakephp 2 multiple OR conditions while retrieving data

I am using multiple OR conditions in my find function, but cakephp overrides it and takes only the latest OR condition, which is very disturbing. Each or conditions focus a different table. This is my custom find function:
$studies = $this -> Study -> find('studyWithSequence',array(
'joins' => array(
array('table' => 'executed_study_tables', // Table name
'alias' => 'ExecutedStudyTable',
'type' => 'LEFT',
'conditions' => array(
'ExecutedStudyTable.study_id = Study.id', // Mention join condition here
)
)
),
'conditions' => array(
'Study.user_id' => $cId,
'OR'=>array(
array('Study.state'=>'active'),
array('Study.state'=>'rehearsal')
),
'SubjectFilter.studyCode'=>null,
'SubjectFilter.m'=>1,
'SubjectFilter.f'=>1,
'SubjectFilter.age18_24'=>1,
'SubjectFilter.age25_34'=>1,
'SubjectFilter.age35_44'=>1,
'SubjectFilter.age45_54'=>1,
'SubjectFilter.age55plus'=>1,
'OR'=>array(
'NOT'=>array(
array('ExecutedStudyTable.user_id'=>$user),
),
array('ExecutedStudyTable.user_id'=>null)
)
),
));
Do you know how to keep both or conditions?
I appreciate your replies
I found a solution.
Normally cakephp 2 concatenate all conditions with AND, but in my case you have to define the AND condition manually. Like this:
$studies = $this -> Study -> find('studyWithSequence',array(
'joins' => array(
array('table' => 'executed_study_tables',
'alias' => 'ExecutedStudyTable',
'type' => 'LEFT',
'conditions' => array(
'ExecutedStudyTable.study_id = Study.id',
)
)
),
'conditions' => array(
'Study.user_id' => $cId,
'OR'=>array(
array('Study.state'=>'active'),
array('Study.state'=>'rehearsal')
),
'SubjectFilter.studyCode'=>null,
'SubjectFilter.m'=>1,
'SubjectFilter.f'=>1,
'SubjectFilter.age18_24'=>1,
'SubjectFilter.age25_34'=>1,
'SubjectFilter.age35_44'=>1,
'SubjectFilter.age45_54'=>1,
'SubjectFilter.age55plus'=>1,
'AND'=>array(
'OR'=>array(
'NOT'=>array(
array('ExecutedStudyTable.user_id'=>$user),
),
array('ExecutedStudyTable.user_id'=>null)
)
)
),
));

CakePHP - select from database with condition

I have this selector:
$this->Table->find('list',array('contain'=>false,'conditions'=>array('status'=>1,'unit_id'=>null,'country_id'=>$countryId,'eday'=>$eday),'fields'=>'id'));
And this works perfect. But now i need to have another one i cant find how to do this ;)
I need to select all records from Table but with condition:
'eday'>=$eday AND 'eday'<$eday+7
Its this posibble in easy way? Maybe this is stupid question but i dont have exp in PHP ;)
In cakephp the equivalent for and condition is
Example: column1 = 'value' AND column2 = 'value'
'AND' => array(
'column1' => 'value',
'column2' => 'value'
)
So your query builder would be like this
$this->Table->find('list',array(
'contain' => false,
'conditions' => array(
'status' => 1,
'unit_id' => null,
'country_id' => $country,
'AND' => array(
'eday >=' => $eday,
'eday <' => ($eday+7)
)
),
'fields'=>'id'
));
Just pass an AND array with in your current conditions array :
$this->Table->find('list',array('contain'=>false, 'conditions'=>array('status'=>1,'unit_id'=>null,'country_id'=>$countryId,'eday'=>$eday, AND => array( array('eday >=' => $eday) , array( 'eday <' => $eday+7) )), 'fields'=>'id' ));
Have you tried something like this :
$conditions['status'] = 1;
$conditions['unit_id'] = null;
$conditions['country_id'] = $countryId;
$conditions['eday >='] = $eday;
$conditions['eday <'] = $eday + 7;
$this->Table
->find('list') //either use this
->find('all') //or use this
->find() //or this
->where($conditions)
->select(['addFiledsToSelectHere'])
This looks more cleaner.

get data using not ids not working in cakephp

I want to select data for all rows where the below ids dont exist. I thought this would work but there is no error and the below ids still appear in the retrieved records. I am using cakephp 2.5 for this
$ids///
array(
(int) 0 => '14721',
(int) 1 => '14731',
(int) 2 => '14905',
(int) 3 => '15808',
(int) 4 => '15818',
$test=$this->Lessonbak->find('all', array(
'fields'=>array('id'),
'recursive' => -1 ) );
$ids=array();
foreach( $test as $item):
array_push($ids,$item['Lessonbak']['id']);
endforeach;
$lessonstudent2=$this->LessonsStudent2->find('all', array(
'conditions' => array( "NOT" => array( 'LessonsStudent2.lesson_id' => $ids )),
'recursive' => -1 ) );
Instead of selecting all of the Lessonbak ids, pushing them to an array, and using that in your LessonsStudent2 query, you should simply use a subquery:
$dbo = $this->getDataSource();
$subquery = $dbo->buildStatement(
array(
'table' => 'lessonbak',
'alias' => 'Lessonbak',
'recursive' => -1,
'fields' => array(
'Lessonbak.id'
)
),
$this
)
$this->LessonsStudent2->find('all', array(
'conditions' => array(
'NOT' => array(
'LessonsStudent2.lesson_id IN (' . $subquery . ')'
)
)
)

CakePHP find condition for a query between two dates

I have a start and an end date in my database and a $date variable from a form field. I am now trying to query all the rows where $date is either = start/end date in the db, or ANY date between those two.
It's kind of the opposite of what is described in the docs of how daysAsSql works. I can't figure out how to get it to work. The following line does not work as a find condition in the controller:
'? BETWEEN ? AND ?' => array($date, 'Item.date_start', 'Item.date_end'),
Any help is greatly appreciated. This is driving me crazy.
Here is the complete Query and corresponding SQL:
$conditions = array(
'conditions' => array(
'and' => array(
'? BETWEEN ? AND ?' => array($date, 'Item.date_start', 'Item.date_end'),
'Item.title LIKE' => "%$title%",
'Item.status_id =' => '1'
)));
$this->set('items', $this->Item->find('all', $conditions));
WHERE (('2012-10-06' BETWEEN 'Item.date_start' AND 'Item.date_end') AND (`Item`.`title` LIKE '%%') AND (`Item`.`status_id` = 1))
$conditions = array(
'conditions' => array(
'and' => array(
array('Item.date_start <= ' => $date,
'Item.date_end >= ' => $date
),
'Item.title LIKE' => "%$title%",
'Item.status_id =' => '1'
)));
Try the above code and ask if it not worked for you.
Edit:
As per #Aryan request, if we have to find users registered between 1 month:
$start_date = '2013-05-26'; //should be in YYYY-MM-DD format
$this->User->find('all', array('conditions' => array('User.reg_date BETWEEN '.$start_date.' AND DATE_ADD('.$start_date.', INTERVAL 30 DAY)')));
Here is CakePHP BETWEEN query example.
I'm defining my arrays as variables, and then using those variables in my CakePHP find function call:
// just return these two fields
$fields = array('uri', 'page_views');
// use this "between" range
$conditions = array('Event.date BETWEEN ? and ?' => array($start_date, $end_date));
// run the "select between" query
$results = $this->Event->find('all',
array('fields'=>$fields,
'conditions'=>$conditions));
Ref from
General Example For CakePHP 2.x Query
$_condition = array("TABLENAME.id" => $id, "TABLENAME.user_id" => array_unique($_array), 'date(TABLENAME.created_at) BETWEEN ? AND ?' => array($start_date, $end_date));
$result_array = $this->TABLENAME->find("all", array(
'fields' => array("TABLENAME.id", "TABLENAME.user_id", 'TABLENAME.created_at'),
"conditions" => $_condition,
"group" => array("TABLENAME.id"), //fields to GROUP BY
'joins' => array(
array(
'alias' => 'T2',
'table' => 'TABLENAME2',
'type' => 'LEFT',
'conditions' => array('TABLENAME.t_id = TABLENAME2.t_id')
),
array(
'alias' => 'T3',
'table' => 'TABLENAME3',
'type' => 'LEFT',
'conditions' => array(
'IF(
TABLENAME.t3_id > 0,
T2.f_id = T3.f_id,
TABLENAME.ff_id = T2.ff_id
)'
)
),
),
'recursive' => 0
)
);
This is more efficient and understandable IN BETWEEN query in cakephp 2.x
$testing_log_device_site_name = $testingLogData['TestingLogDevice']['Siteid'];
$conditions = array('TestingLogDevice.dateee BETWEEN ? and ?' => array($start_date, $end_date));
$results = $this->TestingLogDevice->find('all',
array(
'fields'=>array('dateee','timeee','Siteid'),
'conditions'=>array($conditions, 'TestingLogDevice.Siteid'=>$testing_log_device_site_name)
)
);
pr($results);
$data=$this->post->find('all')->where([ 'id'=>$id,
'price between'=>$price1,'and'=>$price2])->toArray();
This query works as following:
select * from post where id=$id and price between $price1 and $price2;
" -- 'price between'=>$price1 --" become "price between $price1"
Use this
$today = new DateTime( date('Y-m-d'));
$fiveYearsBack = $today->sub(new DateInterval('P5Y'));

Cakephp $this->paginate with custom JOIN and filtering options

I've been working with cakephp paginations options for 2 days. I need to make a INNER Joins to list a few fields, but I have to deal with search to filter results.
This is portion of code in which I deal with search options by $this->passedArgs
function crediti() {
if(isset($this->passedArgs['Search.cognome'])) {
debug($this->passedArgs);
$this->paginate['conditions'][]['Member.cognome LIKE'] = str_replace('*','%',$this->passedArgs['Search.cognome']);
}
if(isset($this->passedArgs['Search.nome'])) {
$this->paginate['conditions'][]['Member.nome LIKE'] = str_replace('*','%',$this->passedArgs['Search.nome']);
}
and after
$this->paginate = array(
'joins' => array(array('table'=> 'reservations',
'type' => 'INNER',
'alias' => 'Reservation',
'conditions' => array('Reservation.member_id = Member.id','Member.totcrediti > 0' ))),
'limit' => 10);
$this->Member->recursive = -1;
$this->paginate['conditions'][]['Reservation.pagamento_verificato'] = 'SI';
$this->paginate['fields'] = array('DISTINCT Member.id','Member.nome','Member.cognome','Member.totcrediti');
$members = $this->paginate('Member');
$this->set(compact('members'));
INNER JOIN works good, but $this->paginations ignore every $this->paginate['conditions'][] by $this->passedArgs and I cannot have idea how I can work it out.
No query in debug, just the original INNER JOIN.
Can someone helps me ?
Thank you very much
Update:
No luck about it.
I've been dealing with this part of code for many hours.
If I use
if(isset($this->passedArgs['Search.cognome'])) {
$this->paginate['conditions'][]['Member.cognome LIKE'] = str_replace('*','%',$this->passedArgs['Search.cognome']);
}
$this->paginate['conditions'][]['Member.sospeso'] = 'SI';
$this->Member->recursive = 0;
$this->paginate['fields'] = array(
'Member.id','Member.nome','Member.cognome','Member.codice_fiscale','Member.sesso','Member.region_id',
'Member.district_id','Member.city_id','Member.date','Member.sospeso','Region.name','District.name','City.name');
$sospesi = $this->paginate('Member');
everything goes well, and from debug I receive the first condition and the conditions from $this->paginate['conditions'][]['Member.cognome LIKE'], as you can see
array $this->passedArgs
Array
(
[Search.cognome] => aiello
)
Array $this->paginate['conditions'][]
(
[0] => Array
(
[Member.cognome LIKE] => aiello
)
[1] => Array
(
[Member.sospeso] => NO
)
But, if I write the joins with paginate , $this->paginate['conditions'][] will ignore all the stuff, and give me from debug, just $this->paginate['conditions'][]['Reservation.pagamento_verificato'] = 'SI';
Another bit of information.
If I put all the stuff dealing with $this->paginate['conditions'][]['Reservation.pagamento_verificato'] = 'SI';
before the $this->paginate JOIN, nothing will be in $this->paginate['conditions'][].
This is an old question, so I'll just review how to do a JOIN in a paginate for others who got here from Google like I did. Here's the sample code from the Widget's Controller, joining a Widget.user_id FK to a User.id column, only showing the current user (in conditions):
// Limit widgets shown to only those owned by the user.
$this->paginate = array(
'conditions' => array('User.id' => $this->Auth->user('id')),
'joins' => array(
array(
'alias' => 'User',
'table' => 'users',
'type' => 'INNER',
'conditions' => '`User`.`id` = `Widget`.`user_id`'
)
),
'limit' => 20,
'order' => array(
'created' => 'desc'
)
);
$this->set( 'widgets', $this->paginate( $this->Widget ) );
This makes a query similar to:
SELECT widgets.* FROM widgets
INNER JOIN users ON widgets.user_id = users.id
WHERE users.id = {current user id}
And still paginates.
I'm not sure if you need those [] - try just doing this:
$this->paginate['conditions']['Reservation.pagamento_verificato'] = 'SI';
I use the conditions when I call paginate method.
$this->paginate($conditions)
This works ok for me, I hope it works for you!
If you have setted previous params, you may use:
$this->paginate(null,$conditions)
This might be help full to someone....
This is how I did complicated joins with pagination in cakephp.
$parsedConditions['`Assessment`.`showme`'] = 1;
$parsedConditions['`Assessment`.`recruiter_id`'] = $user_id;
$this->paginate = array(
'conditions' => array($parsedConditions ),
'joins' => array(
array(
'alias' => 'UserTest',
'table' => 'user_tests',
'type' => 'LEFT',
'conditions' => '`UserTest`.`user_id` = `Assessment`.`testuser_id`'
),
array(
'alias' => 'RecruiterUser',
'table' => 'users',
'type' => 'LEFT',
'conditions' => '`Assessment`.`recruiter_id` = `RecruiterUser`.`id`'
)
,
array(
'alias' => 'OwnerUser',
'table' => 'users',
'type' => 'LEFT',
'conditions' => '`Assessment`.`owner_id` = `OwnerUser`.`id`'
)
),
'fields' => array('Assessment.id', 'Assessment.recruiter_id', 'Assessment.owner_id', 'Assessment.master_id', 'Assessment.title', 'Assessment.status', 'Assessment.setuptype','Assessment.linkkey', 'Assessment.review', 'Assessment.testuser_email', 'Assessment.counttype_2', 'Assessment.bookedtime', 'Assessment.textqstatus', 'Assessment.overallperc', 'UserTest.user_id', 'UserTest.fname', 'UserTest.lname', 'RecruiterUser.company_name', 'OwnerUser.company_name'),
'limit' => $limit,
'order'=> array('Assessment.endtime' => 'desc')
);

Resources