For a CakePHP n00b the pagination thing might seem a bit complicated. Well to be frank it is in someways. For instance you can only currently paginate stuff easily when there is a model involved!
For instance here is a pagination with a deep association:
$this->UserProfile->User->Friend->recursive = -1; $this->set('userFriends', $this->paginate($this->UserProfile->User->Friend, array('Friend.user_id' => $userid, 'Friend.accepted' => 1))); $this->set('userFriendsWaiting', $this->paginate($this->UserProfile->User->Friend, array('Friend.user_id' => $userid, 'Friend.accepted' => 0, 'Friend.rejected' => 0))); $this->set('userFriendsRejected', $this->paginate($this->UserProfile->User->Friend, array('Friend.user_id' => $userid, 'Friend.accepted' => 0, 'Friend.rejected' => 1)));
in this it is to ensure that you have the paginate var set in your Friend Model – and that each conditions field (the stuff in the array() is prefixed with the table of this model
Hope this clears it up
I sometimes think it is useful to see exactly what variables (and values are being passed to the view in cakePHP), especially if the project you are working on is complex with much pseudo repetitive data.
A simple solution to do this is to insert this piece of code in your view:
foreach ($this->getVars() as $name) { pr($$name); }
Right,
When I started out on this I hit t’internet looking for any kind of hints as to the best way of going about this. The first thing I came across was the use of a Self Referential HABTM relationship ( User<-HABTM->User ), naturally not being the uber Cake Nerd this really didnt work out too well for me ( although if you want to do it this way it will work if you follow my previous post about redirects after save() ).
So after deciding to scrap the HABTM relationship and move over to a hasMany() / belongsTo() association things became much easier.
I have the following tables:
basically in this friends acts as the “HABTM” join table (basically it is the table we write the associations into – user_id(1) is friends with user_id(2) blah blah blah).
My friends model looks like this:
class Friend extends AppModel { var $name = 'Friend'; }
Nice eh?
Ok my user profile has the following(stripped down for conciseness). I use Bake for my code generation as it generally does a much better job at finding associations – just bear in mind that you will need to have good DB design skills and remember to name foreign keys correctly for it to work.
class User extends AppModel { var $name = 'User'; var $validate = array( 'username' => array('notempty'), 'password' => array('notempty'), 'group_id' => array('numeric'), 'active' => array('numeric'), 'email' => array('email'), var $belongsTo = array( 'Group' => array( 'className' => 'Group', 'foreignKey' => 'group_id', 'conditions' => '', 'fields' => '', 'order' => '' ) ); var $hasMany = array( 'Friend' => array( 'className' => 'Friend', 'foreignKey' => 'user_id', 'dependent' => false, 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'exclusive' => '', 'finderQuery' => '', 'counterQuery' => '' ) ); var $hasAndBelongsToMany = array( 'Group' => array( 'className' => 'Group', 'joinTable' => 'groups_users', 'foreignKey' => 'user_id', 'associationForeignKey' => 'group_id', 'unique' => true, 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' ) ); }
And basically that is it. You will need a piece of code in your controller (or model I guess) that actually adds the friend (ask and you shall receive:)
function addfriend($user_id, $friend_id) { //$user_id = $this->Session->read('User'); //when logged in disabled for testing $this->data['Friend']['user_id'] = $user_id; $this->data['Friend']['friend_id'] = $friend_id; $this->data['Friend']['accepted'] = 0; $this->data['Friend']['rejected'] = 0; //print_r($this->data); $this->User->Friend->Create(); $count = $this->User->Friend->find('count', array('conditions' => array( 'user_id' => $user_id, 'friend_id' => $friend_id))); if( $count < 1) { if($this->User->Friend->save($this->data)){ $this->Session->setFlash('Friend Added'); $this->redirect('/user_profiles/view/'.$this->User->UserProfile->profileID($user_id)); exit; } else { $this->Session->setFlash('Error Adding Friend'); exit; } } else { $this->Session->SetFlash('That Friend Exists'); $this->redirect('/user_profiles/view/'.$this->User->UserProfile->profileID($user_id)); exit; } }
One thing ill state is that the whole
$count = $this->User->Friend->find('count', array('conditions' => array( 'user_id' => $user_id, 'friend_id' => $friend_id))); if( $count < 1) {
is pretty lame on my part – the correct way would be to create a validation rule in your model but im in a bit of a rush and just need to get this part working.
Hope this helps – obviously you just call /users/addfriend/1/2 or something similar to add a friend and then the rest should all come together.
Dan
Have run into a few problems recently with various aspects of CakePHP – the main one is CakePHP writing random rows to a table when calling the save() method for a model.
For example:
function addfriend($user_id, $friend_id) { $this->data['Friend']['user_id'] = $user_id; $this->data['Friend']['friend_id'] = $friend_id; $this->data['Friend']['accepted'] = 0; $this->data['Friend']['rejected'] = 0; $this->User->Friend->Create(); if($this->User->Friend->save($this->data)){ echo ("Friend Added"); } else { echo ("Error Adding Friend"); } }
Will cause several rows to be written to the database when only one is required. This is because there is no redirect / exit statement so the script is trying to return to the same page and method several times.
However this code will work correctly:
function addfriend($user_id, $friend_id) { $this->data['Friend']['user_id'] = $user_id; $this->data['Friend']['friend_id'] = $friend_id; $this->data['Friend']['accepted'] = 0; $this->data['Friend']['rejected'] = 0; $this->User->Friend->Create(); if($this->User->Friend->save($this->data)){ $this->Session->setFlash('Friend Added'); $this->redirect('users/view/'.$user_id); exit; } else { $this->Session->setFlash('Error Adding Friend'); exit; } }