I need a simple add a friend feature in my application, through some research, I would need a join table linking back to users table ? something like this: (I already have a users table)
Users-Friendships-Users
Can anyone give more details about this?
The friendships table should have following columns:
id Integer
user_from (the user who requested friendship)
user_to (the user who accepted friendship)
created (optional to track when your friendship started)
Then you need to create proper Model relation.
class User extends AppModel {
...
var $hasMany = array(
'UserFrom'=>array(
'className'=>'Friendship',
'foreignKey'=>'user_from'
),
'UserTo'=>array(
'className'=>'Friendship',
'foreignKey'=>'user_to'
)
);
var $hasAndBelongsToMany = array(
'Friendship' => array(
'className' => 'User',
'joinTable' => 'friendships',
'foreignKey' => 'user_from',
'associationForeignKey' => 'user_to'
);
...
}
class Friendship extends AppModel {
...
var $belongsTo = array(
'UserFrom'=>array(
'className'=>'User',
'foreignKey'=>'user_from'
),
'UserTo'=>array(
'className'=>'User',
'foreignKey'=>'user_to'
)
)
...
}
This way you are defining 2 relation in each model. You can add HABTM relation too. Run bake script to build your controllers and views. Then in your code you can use something like this:
$this->User->UserFrom->find('all',
array(
'conditions'=>array('user_from'=>1),
'contain'=>array('UserTo')
)
);
This should return friends of user with ID 1 and all friends details.
Be careful with the recursive queries. :)
Related
I am trying to implement a comment and reply (on comments) system using cakePHP. I am storing both comments and replies in a common table
comments<d, post_id, user_id, text, created, type>
using the following code. Here type is an enum with possible values comment and reply.
//File: Models/Comment.php
class Comment extends AppModel{
public $hasMany = array(
'Reply' => array(
'foreignKey' => 'post_id',
'className' => 'Comment',
'conditions' => array('Comment.type'=>'reply')
)
);
}
class Reply extends AppModel{
public $belongsTo = array(
'Comment'=> array()
)
);
}
I suppose the code is self explanatory. I came only this far, but the association is not working.
I'm currently developing a project using CakePHP where users can create projects. Each project has only one administrator user, but other users should be able to "view" the project. How should I create this "view" option to users?
I've already done the following model associations:
[Users Model] hasMany [Projects] (by the time each user can have many projects).
I'm kinda perplexed now and I don't know exactly what additional model association i should create :/ I think a belongsTo or a HasAndBelongsToMany but i'm not sure :/ Can you help me out here?
thank you in advance!
You need to have 3 database tables
users
projects - This table needs to have a column (administrator) which contains the user_id representing the user who is the administrator
usersprojects - This table is cross reference table between the users and projects representing the members of a project
CakePHP Models
User
public $useTable = 'users';
public $hasMany = array(
'ProjectAsAdmin' => array(
'className' => 'Project')
);
public $hasAndBelongsToMany = array(
'ProjectAsMember' => array(
'className' => 'Project')
);
Project
public $useTable = 'projects';
public $hasAndBelongsToMany = array(
'Member' => array(
'className' => 'User')
);
public $belongsTo = array(
'Administrator' => array(
'className' => 'User',
'foreignKey' => 'administrator'
)
);
I'm trying to do one of two things, use a virtual field from a model as the display field in my join model, or use the virtual field as the display in a find('list') on my join model.
Here's the current layout:
MODELS
<?php
class Participant extends AppModel {
public $hasMany = array('Registration');
public $virtualFields = array(
'full_name' => 'CONCAT(last_name, ", ", first_name)'
);
public $displayField = 'full_name';
}
-----
class Contest extends AppModel {
public $hasMany = array('Registration');
}
-----
class Registration extends AppModel {
public $belongsTo = array('Participant', 'Contest');
public $hasMany = array('Assignment');
}
?>
Tables are as follows:
participants contests registrations
------------ --------- --------------
id id id
first_name name contest_id
last_name participant_id
In my contests controller I'm trying to develop a list to be viewed as checkboxes in the view.
Here is the excerpt from my contests controller:
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
)
);
//$contestId is defined previously, and I have verified such.
This all actually runs fine as it is, and in the view will display a column of checkboxes with the registration_id as the label next to the checkbox.
I would like to get a full_name as is defined in the Participant model to be the displayField of the Registration model. I've been searching and can't quite seem to find a good way of doing that. I hope I have been descriptive enough, and please let me know if you have any questions and I'll try to explain better. Thank you.
edit: I'm using CakePHP 2.4.
try to add the 'fields' parameter
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'fields' => array('Registration.id', 'Participant.full_name'),
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
));
edit: apparently cake does not place virtual fields of associated models when using find() with 'fields' options.
So you have to build your array by yourself, hoping your models use the containable behavior
$registrations = $this->Registration->find(
'all',
array(
'contain' => array(
'Participant' => array('full_name')
),
'conditions' => array('contest_id' => $contestId),
)
);
$registrations = Hash::combine($registrations, '{n}.Registration.id', '{n}.Participant.full_name');
$this->set('registrations', $registrations);
I have a 'patient_cases' table with a HABTM relationship with a 'procedures' table. This 'procedures' tables has a many to one relationship with 'consultants' table, which then has a many to one relationship with 'specialties' table.
The relationships are working fine and using cakephp debug tool bar i can see everything is coming through correctly when i look at 'patient_cases' index page, however i'm only getting consultant_id and specialty_id rather than all of the fields with that associated model.
which is what should be happening i believe -
In CakePHP some associations (belongsTo and hasOne) performs automatic
joins to retrieve data, so you can issue queries to retrieve models
based on data in the related one.
But this is not the case with hasMany and hasAndBelongsToMany
associations.
I want to be able to get the consultant name from 'consultants' table using procedures.consultant_id and get the specialty name from 'specialties' using consultant.specialty_id.
I have tried playing about with some table joins but with no success,
class PatientCase extends AppModel {
public $hasAndBelongsToMany = array(
'Procedure' => array(
'className' => 'Procedure',
'joinTable' => 'patient_cases_procedures',
'foreignKey' => 'patient_case_id',
'associationForeignKey' => 'procedure_id',
'unique' => true
)
);
}
class Procedure extends AppModel {
public $belongsTo = array(
'Consultant' => array(
'className' => 'Consultant'
)
);
}
class Consultant extends AppModel {
public $belongsTo = array(
'Specialty' => array(
'className' => 'Specialty',
'conditions' => array('Specialty.active' => 1)
)
);
public $hasMany = array(
'Procedure'
);
}
class Specialty extends AppModel {
public $hasOne = array(
'Consultant'
);
);
}
$this->set('patientCases', $this->PatientCase->find('all'));
Returns everything i need, each model array is returned (other relationships not mentioned here), however the model array 'Consultant' is not returned, which also means i can not get the 'Specialty' data which is linked to the 'Consultant' model
EDIT
I have managed to get the data i need by using this in my PatientCasesController
$this->set('patientCases', $this->PatientCase->find('all'));
$this->set('patientCaseProcedures', $this->PatientCase->Procedure->find('all'));
However, ideally i want to return everything in the one 'patientCases', is this possible?
EDIT
I have solved the problem using the recursive function
$this->PatientCase->recursive = 3;
$this->set('patientCases', $this->PatientCase->find('all'));
Someone can help me on this issue please?
How to join table on specific field?
I have 2 tables and I want to join them like this: Actus.user_id=>Follows.follower_id
table 1 =>
Follows
id
user_id
follower_id
table 2 =>
Actus
id
user_id
content
created
Forcing a join is done like this (on top of my head):
<?php
$results = $this->Actu->find('all',
array('joins'=> array(
'table'=>'followers',
'type'=>'inner',
'alias'=>'Follower',
'conditions'=>array(
'Follower.follow_id = Actu.user_id',
)
)
)
?>
But you would normally don't need forcing joins. CakePhp can build this for you, if your Models (Actu and Follower) are declared properly. What about setting a "Actu" hasMany "Follower" relationship ? See here
EDIT :
I would do it like this (I am not sure about the exact model name, double check it) :
<?php
class Actu extends AppModel {
public $hasMany = array(
'Follow'=> array(
'className' => 'Follow',
'foreignKey' => 'follower_id'
)
);
}
?>