0

I can't help myself and it's currently annoying, and yes, I used google a lot.

What I need:

A twitterlike follow button with the action to follow user.

What I already did:

Database

users table: id, username, password, ...

users_users table: id, user_id, follower_id

Code

In model User.php

public $hasAndBelongsToMany = array(
'Follower' => array(
  'className' => 'User',
  'joinTable' => 'users_users',
  'foreignKey' => 'user_id',
  'associationForeignKey' => 'follower_id',
  'unique' => 'keepExisting',
) 
);

In UsersController.php

public function follow() {
/*need help here*/
}

In Users\index.ctp

<?php if ($current_user['id'] != $user['User']['id']) echo $this->Html->link('Follow', array('action' => 'follow', $user['User']['id'])); ?>
kenwebart
  • 51
  • 2
  • 9

1 Answers1

0

Personally, I don't find hasAndBelongsToMany to be a good fit for situations like this. It's a good fit for when you want to display a list of checkboxes, or a select list, and allow the user to select/manage all their followings (or whatever the relationships might be) in one form.

It might just be my personal preference, but in situations like yours, where you're adding/deleting single links without worrying about any of the other links related to that user, I prefer to just create a separate 'Relationships' (or similarly named) Model / Controller, and consider the records as things in their own right, as opposed to just hasAndBelongsToMany links that are all sort of 'automagically' managed.

Here's how I'd do it:

Name your users_users table 'relationships'. And name the columns 'followed_by_id' and 'following_id' (or similar) to avoid any ambiguity as to which user is the follower / followee (if that was a word!).

In your users Model, you'd have these relationships:

var $hasMany = array(
    'Followers' => array(
        'className' => 'Relationship',
        'foreignKey' => 'following_id',
        'dependent'=> true
    ),
    'FollowingUsers' => array(
        'className' => 'Relationship',
        'foreignKey' => 'followed_by_id',
        'dependent'=> true
    ),
);

Then you'd have a Relationships model that looks something like this (the $belongsTo relationships are the important part):

<?php
class Relationship extends AppModel {
    var $name = 'Relationship';

    var $validate = array(
        'followed_by_id' => array(
            'numeric' => array(
                'rule' => array('numeric'),
            ),
        ),
        'following_id' => array(
            'numeric' => array(
                'rule' => array('numeric'),
            ),
        ),
    );

    var $belongsTo = array(
        'FollowedBy' => array(
            'className' => 'User',
            'foreignKey' => 'followed_by_id'
        ),
        'Following' => array(
            'className' => 'User',
            'foreignKey' => 'following_id'
        )
    );
}
?>

And then in your Relationships controller, you'd have something like this:

function add($following_id = null) {
    $this->Relationship->create();
    $this->Relationship->set('followed_by_id',$this->Auth->User('id'));
    $this->Relationship->set('following_id',$following_id);
    if ($this->Relationship->save($this->data)) {
        // all good
    } else {
        // You could throw an error here if you want
        $this->Session->setFlash(__('Error. Please, try again.', true));
    }
    $this->redirect($this->referer());
}

Then to add relationships, you obviously just call the add method of your relationships controller.

NOTE: Ideally, since adding a relationship is changing the database, it ideally shouldn't be done with a GET request accessed by a regular URL. It should be done via submitting a form via POST. I know that seems overkill when it's so easy to just do it via a regular link with GET. I haven't bothered to use forms/POST in this example - but if you want to stick to best practices, that's what you should do. See this for more info: https://softwareengineering.stackexchange.com/questions/188860/why-shouldnt-a-get-request-change-data-on-the-server

Community
  • 1
  • 1
joshua.paling
  • 13,762
  • 4
  • 45
  • 60