nate, Sam D: thank you for your replies!

> could be this one
> http://othy.wordpress.com/2006/06/03/unbind-all-associations-except-s...
> Sam D

Yes, I'm using Oth's method mainly in an effort to optimize my
applications as a last phase - to remove unnecessary DB queries. I
didn't feel it was worth mentioning. In this particular case I'm using
it to cut off the rest of the associated models in order to get a
cleaner output arrays.

> Take the associations out of your UserFriend model.  They're implied,
> as UserFriend is already being used to join User and Friend.

Yes, they're implied, but when I remove them I'm not able to fetch
anything beyond UserFriend when issuing $this->User->UserFriend-
>findAll():

        Outgoing_requests: Array
        (
            [0] => Array
                (
                    [FanFriend] => Array
                        (
                            [id] => 1
                            [fan_id] => 1
                            [friend_id] => 2
                            [requested] => 2007-11-21 16:23:50
                            [accepted] =>
                            [active] => 0
                        )
                )

            [1] => Array
                (
                    [FanFriend] => Array
                        (
                            [id] => 5
                            [fan_id] => 1
                            [friend_id] => 3
                            [requested] => 2007-11-26 18:13:59
                            [accepted] =>
                            [active] => 0
                        )

                )
        )

I've been able to find my way through this and these are the steps
I've undertaken to achieve it:

1) As users_friends was violating the principle of alphabetically
ordered foreign keys of the join table, I've renamed the association
model to FanFriend, the corresponding DB table to `fans_friends` and
the foreign key `user_id` to `fan_id`. It still holds semantic meaning
as the user that initiates the friend request could be considered a
fan of the other user, and only after the target user accepts the
request they both become friends

2) I noticed that I've erroneously designated the foreign keys of the
HABTM association. In models/user.php foreign_key and
associationForeignKey should have their places switched.
Was:
    var $hasAndBelongsToMany = array(
        'Friend' => array(
            'className'    => 'User',
            'joinTable'    => 'users_friends',
            'foreignKey'   => 'friend_id',
            'associationForeignKey'=> 'user_id',
            'unique'       => true,
            'with'       => 'UserFriend',
        ),
    );

Is now:
    var $hasAndBelongsToMany = array(
        'Friend' => array(
            'className'    => 'Friend',
            'joinTable'    => 'fans_friends',
            'foreignKey'   => 'fan_id',
            'associationForeignKey'=> 'friend_id',
            'with'       => 'FanFriend',
        ),
    );

3) As can be seen in the latest version of the habtm association, not
only the foreign keys have switched places, but I've also changed the
className - it's not User anymore, but is 'Friend'. Yes, I've found
out that I'm not able to fetch associated model data beyond a model
associated via an alias, no matter what the className was. I've come
to this conclusion by setting up a minimalistic version of my scenario
- User hasAndBelongsToMany Friend (className = 'User') and User
hasMany Photo. No matter how high I set the recursive flag of the
findAll() method, I'm only getting the associated photos on the User
side of the association. The Friend side remained bare - nothing
beyond it.
So, I figured the only way to get anything beyond Friend was to
implement a model for the Friend association and bind the Photo model
to it like this:

models/friend.php:
class Friend extends AppModel {
    var $name = 'Friend';
    var $useTable = 'users';

    var $hasMany = array(
        'Photo' => array(
            'className'     => 'Photo',
            'foreignKey'    => 'user_id',
            'order'         => 'Photo.primary DESC, Photo.id ASC',
            'dependent'     => true,
        ),

    );
}

I first tried to avoid creating a dedicated Friend model, by trying in
users_controller.php:
$this->User->FanFriend->Friend->bindModel('Photo'), but it didn't
work, so as a last resort I implemented the model.

This setup now works and here are the definitions in case they might
help someone:

models/user.php:
class User extends AppModel {
    var $name = 'User';

    var $hasMany = array(
        'Photo' => array(
            'className'     => 'Photo',
            'foreignKey'    => 'user_id',
            'order'         => 'Photo.primary DESC, Photo.id ASC',
            'dependent'     => true,
            ),

    );

    var $hasAndBelongsToMany = array(
        'Friend' => array(
            'className'    => 'Friend',
            'joinTable'    => 'fans_friends',
            'foreignKey'   => 'fan_id',
            'associationForeignKey'=> 'friend_id',
            'with'       => 'FanFriend',
        ),
    );
}

models/friend.php
class Friend extends AppModel {
    var $name = 'Friend';
    var $useTable = 'users';

    var $hasMany = array(
        'Photo' => array(
            'className'     => 'Photo',
            'foreignKey'    => 'user_id',
            'order'         => 'Photo.primary DESC, Photo.id ASC',
            'dependent'     => true,
        ),

    );
}

models/fan_friend.php
class FanFriend extends AppModel {
    var $name = 'FanFriend';
    var $useTable = 'fans_friends';

    var $belongsTo = array(
        'User' => array(
            'className'    => 'User',
            'joinTable'    => 'fans_friends',
            'foreignKey'   => 'fan_id',
        ),
        'Friend' => array(
            'className'    => 'Friend',
            'joinTable'    => 'fans_friends',
            'foreignKey'   => 'friend_id',
        ),
    );
}

users_controller.php
    function requests () {
        $user_id = $this->othAuth->user('id');
        if(!$user_id) {
            $this->log('Invalid $user_id returned by othAuth-
>user(\'id \')', 'user');
            $this->redirect('/', null, true);
        }

        // Unbind all associations except for the ones passed in the
argument array.
        // Borrowed from: 
http://othy.wordpress.com/2006/06/03/unbind-all-associations-except-some/
        // It can also be found in one of Oth's articles in the Bakery
        $this->User->unbindAll(
            array(
                'hasMany' => array('Photo'),
                'hasAndBelongsToMany' => array('Friend'),
            )
        );

        $outgoingConditions = array(
            'FanFriend.fan_id' => $user_id,
            'FanFriend.active' => 0,
        );
        $outgoing_requests = $this->User->FanFriend-
>findAll($outgoingConditions,null,null,null,null,2);
        $outs = Set::extract($outgoing_requests, '{n}.Friend');

        $incomingConditions = array(
            'FanFriend.friend_id' => $user_id,
            'FanFriend.active' => 0,
        );
        $incoming_requests = $this->User->FanFriend-
>findAll($incomingConditions,null,null,null,null,2);
        $ins = Set::extract($incoming_requests, '{n}.User');

        // not necessary needed, but removes an unneeded key from each
array element:
        foreach($ins as $key => $user) {
            if(isset($ins[$key]['Friend'])) {
                unset($ins[$key]['Friend']);
            }
        }
        $this->log($outs, 'outgoing_requests');
        $this->log($ins, 'incoming_requests');
    }

Output:
Incoming_requests: Array
(
    [0] => Array
        (
            [id] => 3
            [email] => [EMAIL PROTECTED]
            [username] => JackDaniels
            [password] => 6a496d870428fbe5fbf6ce086ed6a96e
            [active] => 1
            [created] => 2007-10-24 23:43:57
            [modified] => 2007-10-24 23:46:20
            [Photo] => Array
                (
                    [0] => Array
                        (
                            [id] => 26
                            [type] => image/jpeg
                            [ext] => jpg
                            [size] => 1185725
                            [primary] => 1
                            [user_id] => 3
                            [created] => 2007-11-15 14:54:41
                            [updated] => 2007-11-15 14:54:41
                        )
                )
       )
)

Outgoing_requests: Array
(
    [0] => Array
        (
            [id] => 2
            [email] => [EMAIL PROTECTED]
            [username] => nasko2
            [password] => 6a496d870428fbe5fbf6ce086ed6a96e
            [active] => 1
            [created] => 2007-10-24 23:00:33
            [modified] => 2007-10-24 23:01:46
            [Photo] => Array
                (
                    [0] => Array
                        (
                            [id] => 28
                            [type] => image/pjpeg
                            [ext] => jpg
                            [size] => 1492036
                            [primary] => 1
                            [user_id] => 2
                            [created] => 2007-11-22 16:45:55
                            [updated] => 2007-11-22 16:45:55
                        )
                )
       )
)

Sorry for the lengthy posts, but it really took me several days to
figure this one out and if it could help anyone else out there then it
would be worth it. I took the idea from Mariano Iglesias's article
here: 
http://www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1
but as he didn't need  to fetch associated model data from beyond the
aliased side of the HABTM association he did not ellaborate on what
needed to be done to achieve that.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Cake 
PHP" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/cake-php?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to