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 . ')'
)
)
)
Related
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)
)
)
),
));
I am trying to make a query using cakephp model binding. Getting an unexpected result. But whenever I run the query in phpmyadmin it works fine. Getting this error
Column not found: 1054 Unknown column 'Comment.post_id' in 'field list'
Can't figure out what is wrong
PostsController
$posts = $this->Post->find('all', array(
'conditions' => array(
'Post.is_deleted' => 0,
'Post.is_active' => 1,
),
'fields' => array(
'Post.post_id,Post.post_title,Post.post_body,User.username,Post.added_time',
'Product.product_title','COUNT(Comment.post_id) AS total_comment'
),
'GROUP'=>'Post.post_id',
'order' => 'added_time DESC',
));
Post Model
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreign_key' => 'post_id'
),
'Product' => array(
'className' => 'Product',
'foreign_key' => 'post_id'
)
);
public $hasMany = array(
'Comment'=>array(
'className'=>'Comment',
'foreign_key'=>'post_id'
)
);
Comment Model
public $belongsTo = array(
'Post'=>array(
'className'=>'Post',
'foreign_key'=>'post_id'
)
);
My expected query
SELECT posts.`post_title`, users.username,products.product_title, posts.post_body, COUNT(comments.post_id) as total_comments from posts LEFT JOIN comments on comments.post_id = posts.post_id LEFT join users on users.user_id = posts.user_id LEFT JOIN products on products.product_id = posts.product_id WHERE posts.is_active = 1 and posts.is_deleted = 0 GROUP BY posts.post_id
Try by setting the recursive level 1 or 2
$this->Post->find('all', array(
'conditions' => array(
'Post.is_deleted' => 0,
'Post.is_active' => 1,
),
'fields' => array(
'Post.post_id,Post.post_title,Post.post_body,User.username,Post.added_time',
'Product.product_title','COUNT(Comment.post_id) AS total_comment'
),
'GROUP'=>'Post.post_id',
'order' => 'added_time DESC',
'recursive'=>1
));
I have a model called "User" which has a hasMany relationship to "AdvertisementClicks". I want to find all users that have at least 5 clicks (for example) that were made in the past 5 days. I currently have this:
$params = array(
'conditions' => array(
'User.referrer_id' => NULL,
'User.id !=' => $this->Session->read('MySite.User.id')
),
'contain' => array(
'AdvertisementClick' => array(
'conditions' => array(
'CAST(AdvertisementClick.created AS DATE) >=' => date('Y-m-d', strtotime("-4 days"))
)
)
)
);
$this->User->Behaviors->attach('Containable');
$availableReferrals = $this->User->find('all', $params);
But this will find all the users regardless if they made any clicks or not.
And if possible, limit the find to only return 3 users once it found those 3 users have at least 5 clicks.
Thanks!
I assume that AdvertisementClick belongsTo User
$params = array(
'conditions' => array(
'User.referrer_id' => NULL,
'User.id !=' => $this->Session->read('MySite.User.id'),
'COUNT(AdvertisementClick.id) AS clickcount',
'CAST(AdvertisementClick.created AS DATE) >=' => date('Y-m-d', strtotime("-4 days"))
),
'group' => 'AdvertisementClick.id HAVING clickcount >= 5'
);
$availableReferrals = $this->User->AdvertisementClick->find(
'all',
$params
);
Use group by in query, it will give desired result:
$params = array(
'conditions' => array(
'User.referrer_id' => NULL,
'User.id !=' => $this->Session->read('MySite.User.id'),
'COUNT(AdvertisementClick.id) AS clickcount',
'CAST(AdvertisementClick.created AS DATE) >' => date('Y-m-d', strtotime("-4 days"))
),
'contain' => array(
'AdvertisementClick' => array(
'conditions' => array(
'CAST(AdvertisementClick.created AS DATE) >' => date('Y-m-d', strtotime("-4 days"))
)
)
)
'group'=>'AdvertisementClick.id HAVING clickcount >= 5'
);
$this->User->Behaviors->attach('Containable');
$availableReferrals = $this->User->find('all', $params);
In my CakePHP app I have three tables:
Businesses, Towns and Categories.
A business can belong to multiple towns and multiple categories so I have created joining tables and hasMany and belongsTo relationships. Everything works fine when finding businesses by either Town or Category by using the Town or Category model to search, but I am completely stuck when I want to search for businesses in a certain town AND a certain category, eg. Plumbers in London.
The associations just don't seem to work when searching with the Business model and I get column not found errors when trying to use the associated tables. I would think that this would be along the lines of what needs to be done, but I can't get it to work:
$this->set('listings', $this->Business->find('all', array(
'conditions' => array(
'Business.approved' => 1,
'BusinessesCategory.category_id' => $id,
'BusinessesTown.town_id' => $town_id,
'Business.sasite' => 1
)
You need to join the tables to do that.
I will put above a example how has to work with category and you can do the town yourself.
$this->Business->find("all", array(
"joins" => array(
array(
"table" => "businness_categories",
"alias" => "BusinessesCategory",
"type" => "LEFT",
"conditions" => array(
"Businesses.id = BusinessesCategory.business_id"
)
),
array(
"table" => "categories",
"alias" => "Category",
"type" => "LEFT",
"conditions" => array(
"BusinessesCategory.category_id = Category.id"
)
)
),
'conditions' => array(
'Business.approved' => 1,
'Category.id' => $id,
)
));
You also could use a behavior to do that for you:
https://github.com/Scoup/SuperJoin
Hi I had a very similar setup and the same problem. This is how I would solve your problem:
As you dont give away to much of your code I make some assumptions:
- You implemented your search method in the BusinessController
- Your search argument for the town is stored in vaiable $where and the one for Category is stored in $what
Code if you only have conditions for one table
$this->Businesses->Town->recursive = -1;
....
$options['joins'] = array(
array('table' => 'towns',
'alias' => 'Town',
'type' => 'inner',
'conditions' => array(
'Business.town_id = Town.id',
)
)
);
$options['conditions'] = array(
'Town.townName' => $where
);
$result = $this->Business->find('all', $options);
Code if you have conditions for two table
$this->Businesses->Town->recursive = -1;
$this->Businesses->Category->recursive = -1;
....
$options['joins'] = array(
array('table' => 'towns',
'alias' => 'Town',
'type' => 'inner',
'conditions' => array(
'Business.town_id = Town.id',
)
),
array('table' => 'categories',
'alias' => 'Category',
'type' => 'inner',
'conditions' => array(
'Business.category_id = category.id',
)
)
);
$options['conditions'] = array(
'Town.townName' => $where,
'Category.categoryName' => $what
);
$result = $this->Business->find('all', $options);
You can use
$this->Business->find('all', array(
'conditions' => array(
'AND' => array(
'BusinessesTown.town_id' => $town_id,
'BusinessesCategory.category_id' => $id
)
),
'recursive' => 2
));
I have 3 tables: users, specialities, specialities_users.
User HABTM Speciality
Speciality HABTM User
SpecialitiesUser belongsTo Speciality,User
I have also model SpecialitiesUser.
When I want to get specialities for given user I can do it through
SpecialitiesUser->find('all' array('conditions' => array('user_id' => $given_user_id));
Now I want to get all specialities that user NOT belongs to. How I can do this in Cake?
The $other_specialities variable in the following code should be what you want:
$the_users_specialities = $this->SpecialitiesUser->find('list', array(
'conditions' => array(
'SpecialitiesUser.user_id' => $given_user_id
),
'fields' => 'SpecialitiesUser.speciality_id'
));
$other_specialities = $this->Speciality->find('all', array(
'conditions' => array(
'NOT' => array(
'Speciality.id' => $the_users_specialities
)
)
));
UPDATE: This is how to do it using a single query:
$db = $this->Speciality->getDataSource();
$sub_query = $db->buildStatement(
array(
'fields' => array('`SpecialitiesUser`.`speciality_id`'),
'table' => $db->fullTableName($this->SpecialitiesUser),
'alias' => 'SpecialitiesUser',
'conditions' => array('`SpecialitiesUser`.`user_id`' => $given_user_id),
),
$this->Speciality
);
$other_specialities = $this->Speciality->find('all', array(
'conditions' => array(
$db->expression('`Speciality`.`id` NOT IN (' . $sub_query . ')')
)
));