CakePHP joing two tables - cakephp

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

Related

How to get rid of null associated model in cakephp 2.x

I am trying to get the item types that Order.Item.ItemType.show_type = 1. I have written the query but I want to show only Items that their ItemType.show_type = 1 not all items.
$brief = $this->Order->find('first', array(
'fields' => array(
'Order.*'
),
'conditions' => array(
'Order.order_id' => $orderId,
),
'contain' => array(
'Item' => array(
'fields' => array(
'Item.*', 'CHAR(64 + Item.num) AS letter'
),
'conditions' => array(
'Item.deleted' => 0,
),
'ItemType' => array(
'conditions' => array(
'ItemType.show_type' => 1
),
)
),
)
));
The query shouldn't show Item id = 25741
Associations:
// Order
public $hasMany = array(
'BriefInstalment' => array(
'foreignKey' => 'order_id'
)
);
// Item Model
public $belongsTo = array(
'Order',
'ItemType' => array(
'type' => 'inner'
)
);
// ItemType Model
public $hasMany = array('Item');
Print:
array(
'Order' => array(
'order_id' => '67817',
'service' => '',
),
'Item' => array(
(int) 0 => array(
'id' => '25741',
'order_id' => '67817',
'num' => '2',
'item_type_id' => '8',
'name' => '3-5 titles active',
'deleted' => false,
'ItemType' => array(), // <= how to remove this empty model
'Item' => array(
(int) 0 => array(
'letter' => 'B'
)
)
),
(int) 1 => array(
'id' => '25742',
'order_id' => '67817',
'num' => '3',
'item_type_id' => '2',
'name' => '1,000 pro active',
'deleted' => false,
'ItemType' => array(
'id' => '2',
'name' => 'Part Instalment',
'show_type' => true,
'deleted' => false
),
'Item' => array(
(int) 0 => array(
'letter' => 'C'
)
)
)
)
)
This could not be done using Countaible behaviour, but iwth the joins method, set the recursive to -1
$brief = $this->Order->find('first', array(
'recursive' => -1,
'fields' => array(
'Order.*'
),
'conditions' => array(
'Order.order_id' => $orderId,
),
'joins' => array(
array(
'table' => 'items',
'alias' => 'Item',
'type' => 'inner',
'conditions' => array(
'Order.id = Item.order_id'
)
),
array(
'table' => 'item_types',
'alias' => 'ItemType',
'type' => 'inner',
'conditions' => array(
'ItemType.id = Item.item_type_id'
)
),
)
));
You have to check if the table names are correct and also the foreign keys names.
Another solution would be to go through your results, and unset the empty ones
foreach($brief as $k => $v){
foreach($v['Item'] as $kk => $vv){
if(empty($vv['ItemType'])){
unset($brief[$k]['Item'][$kk];
}
}
}
debug($brief);

cant get required records from habtm in 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.

cakephp deep conditions from controller

I am trying to get records from CoursesEmployee model within my BusinessesController. They are not linked directly which is my problem.
Each Business has Employees which can enrol in courses.
BusinessesController.php:
$options = array(
'conditions' => array('Business.' . $this->Business->primaryKey => 1)
);
$test = $this->Business->find('all', $options);
debug($test);
The output:
array(
(int) 0 => array(
'Business' => array(
'id' => '1',
'name' => 'Test Business',
),
'Employee' => array(
(int) 0 => array(
'id' => '1',
'business_id' => '1',
'name' => 'Keith Power',
'Business' => array(
'id' => '1',
'name' => 'Test Business',
),
'Course' => array(
(int) 0 => array(
'id' => '1',
'name' => 'Manual Handling',
'CoursesEmployee' => array(
'id' => '1',
'employee_id' => '1',
'course_id' => '1',
'course_module_id' => '1',
'completed' => true
)
),
(int) 1 => array(
'id' => '3',
'name' => 'Induction',
'CoursesEmployee' => array(
'id' => '2',
'employee_id' => '1',
'course_id' => '3',
'course_module_id' => '0',
'completed' => false
)
)
)
)
)
)
)
I wish to get the list of CoursesEmployee where CoursesEmployee.completed = true and Business.id = 1
Model Associations:
Business $hasMany Employee
Employee $belongsTo Business
Employee $hasAndBelongsToMany Course
public $hasAndBelongsToMany = array(
'Course' => array(
'className' => 'Course',
'joinTable' => 'courses_employees',
'foreignKey' => 'employee_id',
'associationForeignKey' => 'course_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
CoursesEmployee
public $belongsTo = array(
'Employee' => array(
'className' => 'Employee',
'foreignKey' => 'employee_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Course' => array(
'className' => 'Course',
'foreignKey' => 'course_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
cakephp 2.5
I suggest this way, if it doesn't work we'll try join way :
updated :
$coursesEmployes = $this->Business->Employee->CoursesEmployee->find('all',array(
'conditions'=>array('CoursesEmployee.completed '=> 'true' ,'Employee.business_id' => '1' ),
'recursive'=>3)
);
Hope it helps !

CakePHP 2.1 Avg function for query

I am using cakephp 2.1 and I wanna get average of movie ratings for perticular movie.
Where 'Movie' is a model and it contains 'Language' and 'CriticReview' as models.
The array structure is as follows.
array(
(int) 0 => array(
'Movie' => array(
'id' => '4',
'name' => 'Maattrraan',
'cover_image' => '/movies/4d0d1c41d956a2cb2ab93603d1fdf70c.jpg',
'release' => '2012-10-12',
'runtime' => '',
'budget' => '65 crore',
'box_office' => '',
'language_id' => '2',
'industry_id' => '3'
),
'Language' => array(
'id' => '2',
'name' => 'tamil'
),
'CriticReview' => array(
(int) 0 => array(
'rating' => '4',
'movie_id' => '4'
),
(int) 1 => array(
'rating' => '3',
'movie_id' => '4'
)
)
),
(int) 1 => array(
'Movie' => array(
'id' => '1',
'name' => 'Romeo',
'cover_image' => '/movies/32aa2788fa5e1584d4c627c56214574e.jpg',
'release' => '2012-07-06',
'runtime' => '',
'budget' => '',
'box_office' => '',
'language_id' => '1',
'industry_id' => '1'
),
'Language' => array(
'id' => '1',
'name' => 'kannada'
),
'CriticReview' => array(
(int) 0 => array(
'rating' => '6',
'movie_id' => '1'
),
(int) 1 => array(
'rating' => '3',
'movie_id' => '1'
)
)
));
So I have to avg of critic review. Please help me to find out the solution. The work will be appreciable.
I don't know how your query looks like now, but you can try to add this field:
$this->Movie->find("all", array(
"fields" => array("AVG(CriticReview.rating) AS AverageRating"),
"conditions" => ...
));
The array returned will now contain a sub array within each movie with a key 0 like this
[0] => Array
(
[AverageRating] => AVG_CALCULATED_BY_MYSQL
)
I personally prefer to save calculated data instead of calculate it on fly. Maybe you'd like to read this question: MySQL - Calculating fields on the fly vs storing calculated data

Cakephp: associations of associations in "fields"

a post has a user (belongsTo) and a user has a profile (hasOne). Normally everything works: I can access from Post to User and from User to Profile.
From Post, all works using a generic Find. The result is more or less this (I deleted some keys, just for example):
array(
'Post' => array(
'id' => '1',
'category_id' => '1',
'user_id' => '1',
'title' => 'Example',
'text' => '',
),
'User' => array(
'password' => '*****',
'id' => '1',
'group_id' => '1',
'username' => 'mirko',
'status' => 'active',
'Profile' => array(
'id' => '1',
'user_id' => '1',
'first_name' => 'Mirko',
'last_name' => 'Pagliai',
),
)
)
The problem comes when I use "fields", when I want to extract only a few fields.
For example, this works:
'fields' => array('id', 'title', 'User.id')
and the result is:
array(
'Post' => array(
'id' => '1',
'title' => 'Articolo di prova :-)'
),
'User' => array(
'id' => '1'
)
)
But I don't understand, always using "fields", how to access Profile.
These don'yt work:
'fields' => array('id', 'title', 'User.id', 'Profile.id')
'fields' => array('id', 'title', 'User.id', 'User.Profile.id')
I always get this error "Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'User.Profile.id' in 'field list'".
What's wrong? Thanks.
EDIT:
I'm not using the Containable behavior. Maybe is this the problem? Is it essential in this case?
An example, using paginate:
$this->paginate = array(
'conditions' => $conditions,
'fields' => array('id', 'title', 'User.id', 'Profile.id'),
'limit' => 10,
'recursive' => 2,
);
EDIT2:
thanks to #Hoff, I am close to the solution. But there is still something wrong (and Containable is very useful!).
In AppModel.php I added:
...
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
...
But this doesn't work:
$this->paginate = array(
'conditions' => $conditions,
'contain' => array(
'User' => array(
'fields' => array('id'),
'Profile' => array(
'fields' => array('id', 'full_name'),
),
),
'Category' => array(
'fields' => 'title',
),
),
'fields' => array('id', 'user_id', 'category_id', 'title', 'created', 'modified', 'published'),
'limit' => 10,
);
Cause I get:
array(
(int) 0 => array(
'Post' => array(
'id' => '1',
'user_id' => '1',
'category_id' => '1',
'title' => 'Articolo di prova :-)',
'created' => '2012-06-21 18:46:00',
'modified' => '0000-00-00 00:00:00',
'published' => true
),
'Category' => array(
'title' => 'prova',
'id' => '1'
),
'User' => array(
'id' => '1'
)
)
)
but if I add any field to User (email, username, password, etc.), this works:
'User' => array(
'fields' => array('id', 'username'),
'Profile' => array(
'fields' => array('id', 'full_name'),
),
),
And I get:
array(
(int) 0 => array(
'Post' => array(
'id' => '1',
'user_id' => '1',
'category_id' => '1',
'title' => 'Articolo di prova :-)',
'created' => '2012-06-21 18:46:00',
'modified' => '0000-00-00 00:00:00',
'published' => true
),
'Category' => array(
'title' => 'prova',
'id' => '1'
),
'User' => array(
'id' => '1',
'username' => 'mirko',
'Profile' => array(
'id' => '1',
'full_name' => 'Mirko Pagliai'
)
)
)
)
Instead of using the 'recursive' key, I highly suggest using the containable behavior. The documentation on the behavior can be found here. I would suggest applying the behavior in your AppModel so you don't need to add it to all your models. In Model/AppModel.php:
App::uses('Model', 'Model');
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
}
Then, for your pagination:
$this->paginate = array(
'conditions' => $conditions,
'fields' => array('id', 'title'),
'limit' => 10,
'contain' => array(
'User' => array(
'fields' => array('id'),
'Profile' => array(
'fields' => array('id')
)
)
)
);

Resources