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.
Related
I am having problems with the CakePHP belongsTo and hasAndBelongsToMany relationships in CakePHP 2.x
Example situation
Table users
id
organisation_id
Table organisations
id
name
Table user_organisation_permissions
id
user_id
organisation_id
UserModel
hasAndBelongsToMany(Organisation);
belongsTo(Organisation)
A user belongs to one organisation but it has permissions on multiple organisations, resulting in the following conflict:
$aUser = $this->User->findById(1);
print_r($aUser);
// Output
# With the belongsTo relation
array(
'User' => array(
'id' => 1,
'organisation_id' => 1
'name' => 'Test User'
),
'Organisation' => array(
'id' => 1,
'name' => 'Test organisation'
)
);
# With the hasAndBelongsToMany relation
array(
'User' => array(
'id' => 1,
'organisation_id' => 1
'name' => 'Test User'
),
'Organisation' => array(
1 => array(
'id' => 1,
'name' => 'Test organisation'
),
2 => array(
'id' => 1,
'name' => 'Test organisation'
)
)
);
# When both relations are enabled it doesn't work
Does anybody have a solution for this conflict?
Is there a "native" CakePHP solution for this conflict?
The answer is actually in the CakePHP 2.x Cookbook.
Multiple relations to the same model
There are cases where a Model has more than one relation to another Model. For example, you might have a Message model that has two relations to the User model: one relation to the user who sends a message, and a second to the user who receives the message. The messages table will have a field user_id, but also a field recipient_id. Now your Message model can look something like:
class Message extends AppModel {
public $belongsTo = array(
'Sender' => array(
'className' => 'User',
'foreignKey' => 'user_id'
),
'Recipient' => array(
'className' => 'User',
'foreignKey' => 'recipient_id'
)
);
}
Source: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#multiple-relations-to-the-same-model
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
I am trying to display a field from a 3rd table in a relationship, and after checking posts here and the docs, I am still stuck.I have 3 models all related in some way. I have found similar posts here but I am still not getting it to work. I am learning so sorry if I have missed this somewhere in the docs but I have read a fair bit and have tried a lot. I am guessing too much now on this so I need help.
1)Tutorsession - belongsto teachers,
2) Teacher -has 1 user,hasmany tutorsessions
3) User- has 1 teacher, //////I want to display a field from this table given I display tutorsessions
In controller
$this->set('tutor',
$this->Tutorsession->find('first',
array(
'conditions' => array('Teacher.user_id' => $id),
'contain' => 'User.username'
)
)
); //////////no error but no results
from view echo '<td>'. $item['User']['username'].'</td>'; ///////error user undefined
The tutorsession automatically gets rows from teacher table but not user table witht he model setup on a findall.
I want to display a username from the user table. I display the tutorsession table , I then can display the teacher table with the model association but I cant go from the teacher table to the user table to get a user name from the user id as the common field. I have checked the docs below and I am not sure why my code isnt ble to display a username from users table.
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
update: here are the models
class User extends AppModel {
public $hasOne = array(
'Teacher' => array(
'className' => 'Teacher',
'dependent' => true
)
class Tutorsession extends AppModel
{
public $name='Tutorsession';
public $belongsTo = array(
'Teacher' => array(
'className' => 'Teacher',
'foreignKey' => 'teacher_id'
)
class Teacher extends AppModel
{
public $name='Teacher';
public $hasMany = array('Tutorsession');
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
Add containable behavior in your Model
public $actsAs = array('Containable');
Execute following query In controller
$contain = array('Teacher' => array('User'));
$this->set('tutor', $this->Tutorsession->find('first',array(
'conditions' => array('Teacher.user_id' => $id),
'contain' => $contain
)));
Try this:
$this->Tutorsession->recursive = 2;
$this->Tutorsession->Teacher->contain('User');
$this->set('tutor',
$this->Tutorsession->find('first',
array(
'conditions' => array('Teacher.user_id' => $id)
)
)
);
$tutor=$this->Teacher->find('first',
array(
'conditions' => array('Teacher.user_id' => $id)
)
);
debug($tutor); exit();
Your result similar:
'Teacher' => array(
'id' => '1',
'name' => 'abc',
'created' => '1397040385',
'updated' => '1397725860'
),
'User' => array(
'id' => '4',
'name' => 'administrators',
'created' => '1397032953',
'modified' => '1397032953'
),
'Tutorsession' => array(
0=>array(
'id' => '3',
'name'=>'abc',
'created' => '1400729137'
),
1=>array(
'id' => '4',
'name'=>'abc',
'created' => '1400729137'
)
)
Ensure your models are correct
As I understood from the cakephp-documentation, one of the advantages of the 'containable'-Behavior is being able to fetch fewer data if you need fewer data...
But that doesn't seem to work in my case of a connection between users and usergroups.
My associations look like:
Group
hasMany: Membership
User
hasMany: Membership
Membership
belongsTo: User, Group
(I'm not using HABTM, instead use the Model 'Membership' in between to join users and groups).
All Models implement the 'Containable'-Behavior.
Now I want to get all the members of a group with a certain id, only their ids and mail-addresses. My query is built like that:
$members = $this->Membership->find('all', array(
'conditions' => array(
'group_id' => $id
),
'contain' => array(
'User' => array(
'fields' => array('id', 'fullName')
),
)
));
But the resulting array looks like:
array(
(int) 0 => array(
'Membership' => array(
'id' => '1',
'group_id' => '1',
'user_id' => '1',
'role' => 'member'
),
'Group' => array(
'id' => '1',
'name' => 'Foo Group'
),
'User' => array(
'password' => '*****',
'id' => '1',
'name' => 'Dr. Foo'
'mail' => 'foo#bar.baz',
'role' => 'admin'
)
)
)
So there are definietely more fields fetched than I wanted to... (it's the same thing btw wenn I set the 'contain'-key to:
'contain' => array(
'User.fullName', 'User.id'
)
Am I using the containable-behavior wrong?
Your models don't seem to be acting containabl-y at all. Have you set your models to act as containable?
class Post extends AppModel {
public $actsAs = array('Containable');
}
If so, maybe the problem is with the recursion (to avoid getting the Group array with the query). Containable behavior should handle the recursion level on its own, but try setting it on the AppModel just to be sure
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
Your first attempt
'contain' => array(
'User' => array(
'fields' => array('id', 'fullName')
),
)
looks good in terms of syntax, so it probably the actAs thing.
Also, for debugging also, try
$this->Membership->contain('User');
$this->Membership->find('all', array(
'conditions' => array(
'group_id' => $id
));
and see if you get the expected results that way.
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.