How to count the result using find() in CakePHP 2.2.4? - php

I am using Cakephp 2.2.4 and I need to retrive a list of Lead that belongs to the user (id = 106).
The result of the query is:
array(
(int) 0 => array(
'Lead' => array(
'id' => '6',
'user_id' => '106',
'date' => '2012-12-31 22:15:23',
'ip' => '127.0.0.1',
'service_id' => '1',
'location' => 'Rome',
'message' => 'Message Message',
'telephone' => null,
'active' => null
),
'User' => array(
'id' => '106',
'email' => 'daje#daje.it',
'pwd' => '0433c024cb08be13000d59a347e640482843f46f177e95749dc6599c259617fd3491dcb940b47693cbbc7f65a2cc5ef62deca2e600c1be133ad54170f7d1fbd1',
'role_id' => '3',
'active' => '1'
),
'Service' => array(
'id' => '1',
'name' => 'Primo servizio'
),
'Estimate' => array(
(int) 0 => array(
'id' => '1',
'lead_id' => '6',
'user_id' => '106'
)
)
)
)
It looks good but I need to count the Estimates (Estimate array), I would like to retrive the number of the estimates, and not the array with all the fields (of estimates table).
How can i do it?
I need :
Lead array as it shown
User array as it shown
Service array as it shown
Estimate (only the total number of the estimates... in this case 1)
The find is very simple:
$options = array('conditions' => array('User.id' => 106));
debug($this->Lead->find('all', $options));

Try something like this, not 100% sure it'll work but worth a go if not I'd advise trawling the cakephp docs for retrieving your data:
$options = array(
'fields' => array('Lead.*', 'User.*', 'Service.*', 'count(Estimate.id)'),
'conditions' => array('User.id' => 106)
);

Without diving too far into the internals of the Cake ORM, assuming you don't need to do this immediately at query time, couldn't you just get the count of the estimate array programmatically after the fetch?
http://php.net/manual/en/function.count.php
$leads = $this->Lead->find('all',$options);
foreach($leads as $lead){
//get the number of estimates for every lead result
$lead_num = count($lead['Estimate']);
}
Alternatively, you could manually write a join query for this one fetch and execute it using the Cake Model class's query method. Without knowing the specifics of your table schema and model relations its hard to give specifics about how to structure the query, but this shouldn't be too difficult by just look at your table spec and extracting a sql COUNT statement for every Estimate with given id.

Related

CakePHP - saveAssociated/saveAll behaves like saveMany

I have two Models, namely Product and ProductSpecification which have the following relations in place:
(Product Model)
public $hasMany = array(
'ProductSpecification' => array(
'className' => 'ProductSpecification',
'foreignKey' => 'product_id',
'dependent' => true
)
);
and
(ProductSpecification Model)
public $belongsTo = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id'
)
);
Using the CakePHP Form helper I post ProductSpecification data and then I use the saveAll method (or saveAssociated, I've tried both) to save the data. debug($this->request->data) gives me the following output after POSTing:
array(
'Product' => array(
'id' => '2'
),
'ProductSpecification' => array(
'title' => 'test',
'step' => '1',
'position' => '1'
)
)
This is great, right..? Now, the line after the debug I use the following code to save (I've also tried saveAssociated):
if($this->Product->saveAll($this->request->data))
For some odd reason this saves three(!) empty rows in my ProductSpecification table, with only the product_id field (and id) set; the fields title, step and position are empty. Exactly the same behavior happens when I run saveAssociated. What am I doing wrong?
I'm running CakePHP 2.x.
Your save data should look more like this:-
array(
'Product' => array(
'id' => '2'
),
'ProductSpecification' => array(
array(
'title' => 'test',
'step' => '1',
'position' => '1'
)
)
);
The values for ProductSpecification need to be passed as a numerically indexed array for the hasMany relationship.
Also, make sure you use saveAssociated() rather than saveAll() as you are passing associated data so there is no need to use the wrapper method (which should be avoided wherever possible).

Cant get data from 2 tables using containable in cakephp

I cant get data from 2 tables with conditions on each.
There is no example in the docs.
I just need rows from students table where a field is flagged as inactive and corresponding rows from Guardian table the email field is not null.
Guardian has many Students.
I get results but I get null values for Guardian email.
I have tried many combinations with ID, model name etc but I am just not getting it.
$guardianFound = $this->Student->find('all', array(
'contain' => array( 'Guardian', array(
'conditions' => array('guardian_email !=' => null),
'fields' => array('id,guardian_email','guardian_first_name,guardian_last_name')
)),
'conditions' => array('student_inactive' => 1),
'fields'=> array('student_inactive' ),
'recursive'=> -1
));
Result:
(int) 0 => array(
'Student' => array(
'student_inactive' => true
),
'Guardian' => array(
'guardian_email' => '',
'guardian_first_name' => 'Tulay',
'guardian_last_name' => 'Karadavut',
'id' => '100'
)
)
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
It looks like your query is working as expected, except that you probably want to exclude where guardian_email is null OR empty.
To specify multiple values for a field in CakePHP, you can usually wrap it in another array, but for your case, since you're negating NULL and empty, it's a little complicated because of how CakePHP handles db field types. See this question for more info: Cake PHP complex find 'OR' is not working properly with null and empty string. So to simplify it you can set your Guardian conditions like so:
'conditions' => array(
'guardian_email IS NOT NULL',
'guardian_email != ""'
)
You don't need the recursive key here since you're specifying what to contain using containable. So the final find call would be:
$guardianFound = $this->Student->find('all', array(
'contain' => array(
'Guardian' => array(
'conditions' => array(
'guardian_email IS NOT NULL',
'guardian_email != ""'
),
'fields' => array(
'id', 'guardian_email', 'guardian_first_name', 'guardian_last_name'
)
)
),
'conditions' => array('student_inactive' => 1),
'fields' => array('student_inactive')
));
Note that you're finding all inactive students, then only performing the guardian conditions on the guardians associated with that student. If no Guardian record matches the conditions the field would still be returned but with all the values as NULL.
I'm assuming here that because Student belongsTo Guardian, and there would only be one Guardian per Student, you actually want to only return student records where the guardian email is provided. If that's the case, you just need to move the guardian conditions into the main conditions.
$guardianFound = $this->Student->find('all', array(
'contain' => array(
'Guardian' => array(
'fields' => array(
'id', 'guardian_email', 'guardian_first_name', 'guardian_last_name'
)
)
),
'conditions' => array(
'student_inactive' => 1,
'Guardian.guardian_email IS NOT NULL',
'Guardian.guardian_email != ""'
),
'fields' => array('student_inactive')
));

CakePHP getting data form an ID which is inside another table?

Right, so my data returns in the following way,
(int) 0 => array(
'MODEL-XX' => array(
//DATA HERE
'xxs_id' => '11',
'aas_id' => '44',
'vvs_id' => '2'
),
'xxs' => array(
'id' => '11',
'customername' => 'XX name here'
),
'aas' => array(
'id' => '44',
'clientname' => 'aa name here',
'xxs_id' => '11'
),
'vvs' => array(
'id' => '2',
'start' => '1405296000',
'end' => '1405814400',
'users_id' => '1'
)
This works fine, but I want to know how to link my users table to this model. So the details of each user for my VV model would become apart of the data. My MODEL-XX does not have any links with my users table so the place I need to call in the users details are held with my VV model.
I have been looking into this but have not been able to find a simple easy method for doing this?
I was thinking that this would be doable with my model, so I opened my my XX model and added the following within my '$belongsTo' section,
'Users' => array(
'className' => 'Users',
'foreignKey' => 'vvs.users_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
So is there a easy method for linking data like this?
Please give me time, if I have not explained myself right or not enough data, please tell me and let me fix or explain better.
Thanks,
Either set your recusive higher:
$this->MODEL-XX->recursive = 1; //or 2
Or and this should be your prefered way to go, start using the containable behaviour:
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
In your appModel:
public $actsAs = array('Containable');
Then try this find:
$this->MODEL-XX->recursive = -1;
$data = $this-MODEL-XX>find(
'all', array(
'conditions' => $conditions,
'contain' => array('xxs', 'aas', 'vvs', 'user')
)
);
I might be 'vvs.user' but I forgot what is used for deeper models

CakePHP (2.4) Deep Relationship

I have a database:
Companies | Users | Files
- ID - ID - ID
- company_id - user_id
So for my models:
Company hasmany User
User belongsto Company & hasmany File
File belongsto User
How can I list al the files belonging to a company? Without the user and company data? So a single array listing files.
I could fetch all the user IDs followed by a query in File searching with these IDs. But I was wondering, is there a best practice cakePHP way?
I'm fairly new to cake.
Thanks
As far as I know it's not possible to get company files without any user or company data, but you can limit the data by using the Containable behaviour. For example, if you want to get files that belong to a company in the company controller you could use this:
$users = $this->Company->User->find('all', array(
'conditions' => array('User.company_id' => $id),
'fields' => array('id', 'company_id'),
'contain' => array('File'),
));
The result ($users) would look something like this:
array(
0 => array(
'User' => array(
'company_id' => '75',
'id' => '51'
),
'File' => array(
0 => array(
'id' => '399',
'user_id' => '51',
...
),
1 => array(
'id' => '337',
'user_id' => '51',
...
)
...
)
)
1 => array(
'User' => array(
'company_id' => '75',
'id' => '65'
),
'File' => array(
0 => array(
'id' => '450',
'user_id' => '65',
...
),
...
)
)
)
You can then get an array of files using the Hash utility.
$files = Hash::extract($users, '{n}.File.{n}');
Which will give you something like this:
array(
0 => array(
'id' => '399',
'user_id' => '51',
...
),
1 => array(
'id' => '337',
'user_id' => '51',
...
),
3 => array(
'id' => '450',
'user_id' => '65',
...
),
...
)
Don't forget to enable the behaviour. I suggest you do it in your app model by adding the following line:
public $actsAs = array('Containable');
CakePHP will not help you on this and even if want to write mysql query you cant do this by using files table only until and unless you will add company_id in files table.

CakePHP: Retrieving data

I'm stuck in retrieving some sort of data in my view. I have to list information of a certain "Job", which has different attributes already stored in the database.
For example, I'd like to get the field of 'weighting' listed.
The debug($this->viewVars) prints me this (which represents what's stored in the DB):
'JobValues' => array(
(int) 0 => array(
'id' => '1',
'yearly_job_id' => '1',
'institution_type_id' => '1',
'norm_rate' => '5',
'weighting' => '5.00',
'standard_value' => '5.00',
'education_weeks' => '5.0',
'group_distribution' => '0.50',
'YearlyJob' => array(
'id' => '1',
'year_id' => '1',
'job_id' => '1',
'full_time_jobs_needed' => true,
'education_count_needed' => true,
'is_care' => true
),
Normally I would just print this: echo([JobValue][weighting]);, but there is a number in between, so echo([JobValue][1][weighting]); won't lead to success. What could I implement in my view (or model)? Any advice is highly appreciated.
For printing out the data, if there's only one top level of array, just remove it. print_r(array_shift($foo['JobValues']['weighting']));
If there are multiple arrays on the same level, you need to do a foreach to iterate into each one of the record.

Categories