cant get required records from habtm in cakephp - cakephp

In Cakephp I need to get the tutors who teach a subject 'primary English'. Instead I get all the tutors with any subject so the condition gets ignored with no error. There is a habtm relationship between tutors and subjects they teach.
$this->Tutor->Behaviors->load('Containable');
$tutors=$this->Tutor->find('all',array(
'contain' => array('Subject',array( 'conditions'=> array('Subject.name' => 'Primary English'))),
'contain' => array('Subject'),
'recursive' =>-1,
// 'order'=> $orderoptions,
'fields'=>array('Tutor.last_name', 'Tutor.first_name','Tutor.id' ),
));
debug( $tutors);
array(
(int) 0 => array(
'Tutor' => array(
'last_name' => 'Wyers',
'first_name' => 'Adele',
'id' => '13'
),
'Subject' => array()
),
(int) 1 => array(
'Tutor' => array(
'last_name' => 'Payet',
'first_name' => 'Allison',
'id' => '7'
),
'Subject' => array(
(int) 0 => array(
'id' => '4',
'name' => 'English - Year 11',
'TutorsSubject' => array(
'id' => '30',
'tutor_id' => '7',
'subject_id' => '4'
)
),

Remove 'recursive' => -1. This prevents it from selecting relationships recursively. If this still doesn't work then put 'recursive' => 2 in.

Related

cakephp set:extract array generated by find joins

I have cakephp 2.8 project, I have an array returned by Model->find('all',array('joins')) which is something like this
array(
(int) 0 => array(
'Result' => array(
'id' => '1',
'student_id' => '1',
),
'User' => array(
'fullname' => 'Alam'
)
),
(int) 1 => array(
'Result' => array(
'id' => '2',
'student_id' => '11',
),
'User' => array(
'fullname' => 'Student 1'
)
)
);
I want this array as below
array(
(int) 0 => array(
'id' => '1',
'student_id' => '1',
'fullname' => 'Alam'
),
(int) 1 => array(
'id' => '2',
'student_id' => '11',
'fullname' => 'Student 1'
)
);
I tried Set::extract('/Result/.'); , Set::extract('/Result/User/.'); and other variations but I am not getting desired result.
I know I can do it by foreach loop but I want if it can be done by some builtin php or cakephp function.
I haven't managed to use only one function, but, maybe this will do the trick for you:
$t = Hash::mergeDiff(
Hash::extract($inputArray, '{n}.Result'),
Hash::extract($inputArray, '{n}.User')
);
debug($t);

find by conditions with 'members'

I have 3 model:
Association HasMany Service
Service HasBelongs Association and HasMany Member
Member HasBelongs Service
I want find member by association but I find Service by association.
$associations = $this->Member->Service->Association->find('all',
array(
'fields'=>array('id','libelle')
));
the result debug is:
array(
(int) 0 => array(
'Association' => array(
'id' => '1',
'libelle' => 'الادارة العامة للصحة العسكرية'
),
'Service' => array(
(int) 0 => array(
'id' => '1',
'libelle' => 'Divers',
'association_id' => '1'
),
(int) 1 => array(
'id' => '2',
'association_id' => '1'
),
(int) 2 => array(
'id' => '3',
'libelle' => 'مكتب الضبط BO',
'association_id' => '1'
)
)
),
(int) 1 => array(
'Association' => array(
'id' => '2',
'libelle' => 'أعضاء الديوان والمديرين'
),
'Service' => array()
),
(int) 2 => array(
'Association' => array(
'id' => '3',
'libelle' => 'المستشفات والمراكز والمصحات '
),
'Service' => array()
),
(int) 3 => array(
'Association' => array(
'id' => '4',
'libelle' => 'المستشفى العسكري الاصلي للتعليم '
),
'Service' => array()
)
I want find the member by association example: all member that belong to the Association الادارة العامة للصحة العسكرية ie all members of the services 1, 2, 3
You can use 'contain' to do that.
There are some examples in the book: http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html

CakePHP joing two tables

I have a problem in viewing my data ,I need to return a year,ex(2010,2011,2012,2013) instead of returning the year id , I used contain but It did not work , what is the right way to displaying data ?!
Here is the output array:array(
(int) 0 => array(
'IndicatorDatum' => array(
'id' => '188',
'indicator_id' => '2',
'report_year_id' => '2',
'value' => '144063181',
'comment' => '0',
'reference' => '0'
)
),
(int) 1 => array(
'IndicatorDatum' => array(
'id' => '163',
'indicator_id' => '2',
'report_year_id' => '3',
'value' => '178104575',
'comment' => '0',
'reference' => '0'
)
),
(int) 2 => array(
'IndicatorDatum' => array(
'id' => '137',
'indicator_id' => '2',
'report_year_id' => '4',
'value' => '198637602',
'comment' => '0',
'reference' => '0'
)
),
(int) 3 => array(
'IndicatorDatum' => array(
'id' => '5752',
'indicator_id' => '2',
'report_year_id' => '5',
'value' => '1234',
'comment' => null,
'reference' => null
)
),
(int) 4 => array(
'IndicatorDatum' => array(
'id' => '5694',
'indicator_id' => '2',
'report_year_id' => '6',
'value' => '100',
'comment' => '0',
'reference' => '0'
)
),
(int) 5 => array(
'IndicatorDatum' => array(
'id' => '5271',
'indicator_id' => '2',
'report_year_id' => '6',
'value' => '1',
'comment' => '0',
'reference' => '0'
)
)
)
Model
public $belongsTo = array(
'Indicator' => array(
'className' => 'Indicator',
'foreignKey' => 'indicator_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'ReportYear' => array(
'className' => 'ReportYear',
'foreignKey' => 'report_year_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Organisation' => array(
'className' => 'Organisation',
'foreignKey' => 'organisation_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
$this->find('all',array(
'fields' => array('IndicatorDatum.id','IndicatorDatum.indicator_id','IndicatorDatum.report_year_id','IndicatorDatum.value','IndicatorDatum.comment','IndicatorDatum.reference'
),'contain' => array(
'ReportYears'),
'conditions'=>array('IndicatorDatum.indicator_id' =>'2' , 'IndicatorDatum.organisation_id'=>$organisation_id),
'order' => array('IndicatorDatum.report_year_id')
));
You just need to specify the exact fields for each model(including associated models), otherwise only the id is being returned (and it is good, because if it would be all the fields, what if you have some text column in the db with KBs of data - you do not want to retrieve it)
also, please pay attention, that by default(and by cake conventions) model names are singular, so, inside contain it should be ReportYear and not ReportYears.
here is the final query.
$this->find('all', array(
'fields' => array(
'IndicatorDatum.id',
'IndicatorDatum.indicator_id',
'IndicatorDatum.report_year_id',
'IndicatorDatum.value',
'IndicatorDatum.comment',
'IndicatorDatum.reference'
),
'contain' => array(
'ReportYear' => array(
'fields' => array(
'ReportYear.id',
'ReportYear.year' // not sure what you have as a year field name
)
)
),
'conditions' => array(
'IndicatorDatum.indicator_id' => '2',
'IndicatorDatum.organisation_id' => $organisation_id
),
'order' => array(
'IndicatorDatum.report_year_id'
)
)
);

CakePHP find() and related models and conditions

I am calling find() on my Game model in order to get the reviews of that game for a particular platform. The problem is that the find() call doesn't seem to be paying attention to my conditions array. The call returns all the reviews for a game regardless of the platform_id.
I have these model associations:
User hasMany Review
Game hasMany Review
Review belongsTo Game
Review belongsTo User
Game HABTM Platform
This is the find call that I created:
$options = array(
'group' => array(
'Game.id'
),
'joins' => array(
array(
'table' => 'reviews',
'type' => 'LEFT',
'conditions' => array(
'Game.id=reviews.game_id'
)
),
array(
'table' => 'platforms',
'type' => 'LEFT',
'conditions' => array(
'reviews.platform_id=platforms.id'
)
),
array(
'table' => 'users',
'type' => 'LEFT',
'conditions' => array(
'reviews.user_id=users.id'
)
)
),
'fields' => array(
'Game.id', 'Game.name',
'platforms.id', 'platforms.name',
'users.id', 'users.username'
),
'conditions' => array(
'AND' => array(
'NOT' => array('reviews.review_text' => NULL),
'platforms.id' => $pid,
)
),
'limit' => 5
);
$this->Game->find('all', $options);
Here is a sample return for a find() call for platform_id=2:
array(
(int) 0 => array(
'Game' => array(
'id' => '58',
'name' => 'Bioshock 2'
),
'platforms' => array(
'id' => '2',
'name' => 'PlayStation 3'
),
'users' => array(
'id' => '20',
'username' => 'pspmaniac'
),
'Review' => array(
(int) 0 => array(
'id' => '32',
'review_text' => 'This is the PC review.',
'score' => '4',
'user_id' => '20',
'game_id' => '58',
'created' => '2013-04-30 19:59:40',
'platform_id' => '10'
),
(int) 1 => array(
'id' => '33',
'review_text' => 'This is the PS3 review.',
'score' => '7',
'user_id' => '20',
'game_id' => '58',
'created' => '2013-04-30 20:00:04',
'platform_id' => '2'
),
(int) 2 => array(
'id' => '34',
'review_text' => 'This is the XBOX 360 review.',
'score' => '6',
'user_id' => '20',
'game_id' => '58',
'created' => '2013-04-30 20:00:22',
'platform_id' => '1'
)
)
)
);
In the 'Review' index, it returns three reviews for the game (platform ids 10, 2, and 1) when it should only return the review with platform_id=2.
This is my reviews table:
CREATE TABLE reviews
(
id mediumint unsigned not null auto_increment,
review_text mediumint,
score int not null,
user_id mediumint unsigned not null,
game_id mediumint unsigned not null,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (game_id) REFERENCES games (id)
);
So, in the end, the only thing wrong with the returned array is that it contains reviews not only for the condition 'platforms.id=2' but for all platform ids.
Solution
Using Dave's comment, I came up with this solution to my problem using containable:
$this->loadModel('Review');
$this->Review->find('all', array( 'contain' => array('Platform'), 'conditions' => array( 'Review.platform_id' => 2 )
));

Containable Nested models

I have a few nested models which I'm trying to load using Containable behaviour in CakePHP.
Most of it works fine.
However, 1 model that has a hasMany relation only returns 1 object:
$article = $this->News->find('first',array(
'conditions'=>array('News.id'=>$id),
'contain' => array(
'Newslayout',
'Newspicture'=> array(
'NewspicturesProduct' => array(
'Product' => array(
'Brand',
'Category'
)
)))
));
The object only being loaded once is the relation Newspicture hasMany NewspicturesProduct
When I log the queries, I get the following:
SELECT `NewspicturesProduct`.`id`, `NewspicturesProduct`.`x`, `NewspicturesProduct`.`y`, `NewspicturesProduct`.`product_id`, `NewspicturesProduct`.`newspicture_id`, `NewspicturesProduct`.`w`, `NewspicturesProduct`.`h` FROM `edclondon`.`newspictures_products` AS `NewspicturesProduct` WHERE `NewspicturesProduct`.`newspicture_id` = 3
Which gives me 3 results in phpMyAdmin. But only 1 in CakePHP's debug:
'Newspicture' => array(
(int) 0 => array(
'id' => '3',
'news_id' => '2',
'newspicture_file_path' => '5022443f-ddf8-4115-ae57-618e9d60b047.jpg',
'newspicture_file_size' => '1232546',
'order' => null,
'NewspicturesProduct' => array(
'id' => '1',
'x' => '0.180664',
'y' => '0.295312',
'product_id' => '3',
'newspicture_id' => '3',
'w' => '0.286133',
'h' => '0.478125',
'Product' => array(
'id' => '3',
//....
'Brand' => array(
'id' => '6',
//...
),
'Category' => array(
'id' => '6',
//....
)
)
)
)
When retrieving the Newspictures object rather then retrieving the News object, I do get all 3 NewspicturesProduct objects.
It seems to me that the code corresponding the query you showed should be:
$article = $this->News->find('first',array(
'contain' => array(
'Newslayout',
'Newspicture'=> array(
'NewspicturesProduct' => array(
'conditions'=>array('NewspicturesProduct.newspicture_id'=>'3')
'Product' => array(
'Brand',
'Category'
)
)))
));
and not the one you gave...
It seems you need 3 records from NewspicturesProduct. If that then you can try:
$article = $this->News->find('first',array(
'contain' => array(
'Newslayout',
'Newspicture'=> array(
'NewspicturesProduct' => array(
'conditions'=>array(
'limit'=> 3
),
'Product' => array(
'Brand',
'Category'
)
)))
));

Resources