Hi all,

I really tried to pull this thing by myself, but there's always
something that's not working as expected.

I have a user-and-friend situation.
I need to have both the friend requests and the accepted friendships
in the same table. Hence, the extra fields in the HABTM join table.
I also need to be able to retrieve the pending incoming and outgoing
requests for the current user, together with any additionally
associated models (User hasMany Photo, etc.).
I need to be able to paginate and sort those pending requests.
I need to retrieve the currently established friendships for the
current user (logged user id is either user_id or friend_id in the
join table)

Reading through quite some articles, I based my setup on two of them:
http://groups.google.com/group/cake-php/msg/fae9ec58501534e6? by
AD7six
http://www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1
by Mariano Iglesias

Mariano Iglesias describes two alternative approaches (using auto-with
models vs. manually modeling the habtm association). I decided to go
for modeling the join table, because I intended to use AD7six's
Pagination component and I have prior experience with that component
where I had to manually model the habtm join tables.

So, here's my setup:

[models/user.php]:

    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'    => 'User',
            'joinTable'    => 'users_friends',
            'foreignKey'   => 'friend_id',
            'associationForeignKey'=> 'user_id',
            'unique'       => true,
            'with'       => 'UserFriend',
        ),
    );

[models/user_friend.php]:

class UserFriend extends AppModel {
    var $name = 'UserFriend';
    var $useTable = 'users_friends';

    var $belongsTo = array(
        'User' => array(
            'className'    => 'User',
            'joinTable'    => 'users_friends',
            'foreignKey'   => 'user_id',
            'associationForeignKey'=> 'friend_id',
            'unique'       => true,
        ),
        'Friend' => array(
            'className'    => 'User',
            'joinTable'    => 'users_friends',
            'foreignKey'   => 'friend_id',
            'associationForeignKey'=> 'user_id',
            'unique'       => true,
        ),
    );
}

[DB tables]:
CREATE TABLE `users` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `group_id` smallint(6) NOT NULL,
  `email` varchar(100) default NULL,
  `username` varchar(50) NOT NULL,
  `password` varchar(50) default NULL,
  `active` tinyint(1) default '0',
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `username` (`username`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `users_friends` (
 `id` int(11) NOT NULL auto_increment,
 `user_id` int(10) unsigned NOT NULL default '0',
 `friend_id` int(10) unsigned NOT NULL default '0',
 `requested` datetime default NULL,
 `accepted` datetime default NULL,
 `active` tinyint(1) default '0',
 PRIMARY KEY  (`id`),
 KEY `key_fan_friend` (`user_id`,`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `photos` (
  `id` int(11) NOT NULL auto_increment,
  `type` varchar(255) NOT NULL default '',
  `ext` varchar(255) NOT NULL default '',
  `size` int(11) NOT NULL default '0',
  `primary` tinyint(1) default '0',
  `user_id` int(11) NOT NULL,
  `created` datetime default NULL,
  `updated` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Here are my results with this setup:

[controllers/users_controller.php]:

function requests() {
        $user_id = $this->othAuth->user('id');
        $this->User->unbindAll(
            array(
                'hasMany' => array('Photo'),
                'hasAndBelongsToMany' => array('Friend'),
            )
        );
        $outgoingConditions = array(
            'UserFriend.user_id' => $user_id,
            'UserFriend.active' => 0,
        );
        $incomingConditions = array(
            'UserFriend.friend_id' => $user_id,
            'UserFriend.active' => 0,
        );
        $outgoing_requests = $this->User->UserFriend-
>findAll($outgoingConditions);
        $incoming_requests = $this->User->UserFriend-
>findAll($incomingConditions);

        $this->log($outgoing_requests, 'outgoing');
        $this->log($incoming_requests, 'incoming');
}

[app/tmp/logs/incoming.log]
Array
(
    [0] => Array
        (
            [UserFriend] => Array
                (
                    [id] => 3
                    [user_id] => 3
                    [friend_id] => 1
                    [requested] => 2007-11-21 17:43:14
                    [accepted] =>
                    [active] => 0
                )

            [User] => Array
                (
                    [id] => 3
                    [group_id] => 2
                    [email] => [EMAIL PROTECTED]
                    [username] => JackDaniels
                    [password] => 6a496d870428fbe5fbf6ce086ed6a96e
                    [active] => 1
                    [created] => 2007-10-24 23:43:57
                    [modified] => 2007-10-24 23:46:20
                )

            [Friend] => Array
                (
                    [id] => 1
                    [group_id] => 2
                    [email] => [EMAIL PROTECTED]
                    [username] => nasko
                    [password] => 6a496d870428fbe5fbf6ce086ed6a96e
                    [active] => 1
                    [created] => 2007-10-24 22:52:41
                    [modified] => 2007-10-24 22:52:41
                )
        )
)

[app/tmp/logs/outgoing.log]
Array
(
    [0] => Array
        (
            [UserFriend] => Array
                (
                    [id] => 1
                    [user_id] => 1
                    [friend_id] => 2
                    [requested] => 2007-11-21 16:23:50
                    [accepted] =>
                    [active] => 0
                )

            [User] => Array
                (
                    [id] => 1
                    [group_id] => 2
                    [email] => [EMAIL PROTECTED]
                    [username] => nasko
                    [password] => 6a496d870428fbe5fbf6ce086ed6a96e
                    [active] => 1
                    [created] => 2007-10-24 22:52:41
                    [modified] => 2007-10-24 22:52:41
                )

            [Friend] => 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
                )
        )
)

So far, so good - I've achieved an output similar to what Mariano is
describing in his article.
The probelm emerges when I try to retrieve the photos of requesting or
requested users. As Mariano is suggesting, I started to play with the
recursive argument of the findAll() call:

        $outgoing_requests = $this->User->UserFriend-
>findAll($outgoingConditions,null,null,null,null,2);
        $incoming_requests = $this->User->UserFriend-
>findAll($incomingConditions,null,null,null,null,2);
#1. I'm getting notices in the browser output:
Notice (8): Undefined index:  User [CORE\cake\libs\model\datasources
\dbo_source.php, line 772]
Notice (8): Undefined offset:  0 [CORE\cake\libs\model\datasources
\dbo_source.php, line 875]

#2. The log files:
[app/tmp/logs/incoming.log]
Array
(
    [0] => Array
        (
            [UserFriend] => Array
                (
                    [id] => 3
                    [user_id] => 3
                    [friend_id] => 1
                    [requested] => 2007-11-21 17:43:14
                    [accepted] =>
                    [active] => 0
                )

            [User] => 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
                                )

                        )

                    [Friend] => Array
                        (
                        )

                )

            [Friend] => Array
                (
                    [id] => 1
                    [email] => [EMAIL PROTECTED]
                    [username] => nasko
                    [password] => 6a496d870428fbe5fbf6ce086ed6a96e
                    [active] => 1
                    [created] => 2007-10-24 22:52:41
                    [modified] => 2007-10-24 22:52:41
                )

        )

)

[app/tmp/logs/outgoing.log]
Array
(
    [0] => Array
        (
            [UserFriend] => Array
                (
                    [id] => 1
                    [user_id] => 1
                    [friend_id] => 2
                    [requested] => 2007-11-21 16:23:50
                    [accepted] =>
                    [active] => 0
                )

            [User] => Array
                (
                    [id] => 1
                    [email] => [EMAIL PROTECTED]
                    [username] => nasko
                    [password] => 6a496d870428fbe5fbf6ce086ed6a96e
                    [active] => 1
                    [created] => 2007-10-24 22:52:41
                    [modified] => 2007-10-24 22:52:41
                    [Photo] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 27
                                    [type] => image/pjpeg
                                    [ext] => jpg
                                    [size] => 1443536
                                    [primary] => 1
                                    [user_id] => 1
                                    [created] => 2007-11-16 15:56:42
                                    [updated] => 2007-11-16 15:56:42
                                )

                            [1] => Array
                                (
                                    [id] => 18
                                    [type] => image/jpeg
                                    [ext] => jpg
                                    [size] => 1410154
                                    [primary] => 0
                                    [user_id] => 1
                                    [created] => 2007-11-15 01:27:01
                                    [updated] => 2007-11-15 01:27:01
                                )

                            [2] => Array
                                (
                                    [id] => 21
                                    [type] => image/pjpeg
                                    [ext] => jpg
                                    [size] => 1532595
                                    [primary] => 0
                                    [user_id] => 1
                                    [created] => 2007-11-15 12:41:27
                                    [updated] => 2007-11-15 12:41:27
                                )

                            [3] => Array
                                (
                                    [id] => 22
                                    [type] => image/jpeg
                                    [ext] => jpg
                                    [size] => 1395255
                                    [primary] => 0
                                    [user_id] => 1
                                    [created] => 2007-11-15 13:14:33
                                    [updated] => 2007-11-15 13:14:33
                                )

                            [4] => Array
                                (
                                    [id] => 23
                                    [type] => image/jpeg
                                    [ext] => jpg
                                    [size] => 1980160
                                    [primary] => 0
                                    [user_id] => 1
                                    [created] => 2007-11-15 14:54:10
                                    [updated] => 2007-11-15 14:54:10
                                )

                        )

                    [Friend] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 3
                                    [email] => dolor.sitamet
[EMAIL PROTECTED]
                                    [username] => JackDaniels
                                    [password] =>
6a496d870428fbe5fbf6ce086ed6a96e
                                    [active] => 1
                                    [created] => 2007-10-24 23:43:57
                                    [modified] => 2007-10-24 23:46:20
                                    [UserFriend] => Array
                                        (
                                            [id] => 3
                                            [user_id] => 3
                                            [friend_id] => 1
                                            [requested] => 2007-11-21
17:43:14
                                            [accepted] =>
                                            [active] => 0
                                        )

                                )

                            [1] => Array
                                (
                                    [id] => 4
                                    [email] => dolor.sitamet
[EMAIL PROTECTED]
                                    [username] => jackline
                                    [password] =>
6a496d870428fbe5fbf6ce086ed6a96e
                                    [active] => 1
                                    [created] => 2007-10-24 23:50:45
                                    [modified] => 2007-10-24 23:51:45
                                    [UserFriend] => Array
                                        (
                                            [id] => 4
                                            [user_id] => 4
                                            [friend_id] => 1
                                            [requested] => 2007-11-21
17:43:39
                                            [accepted] => 2007-11-21
17:43:39
                                            [active] => 1
                                        )

                                )

                        )

                )

            [Friend] => 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
                )

        )

)

It looks like the associated models for the Friend part of the HABTM
association are not fetched, regardless of the direction of the
request: for incoming friend requests I can see the associated Photo
model of the requesting user, but for requests that I initiate I
cannot see the photos of the target user...

Judging from the above mentioned articles I shouldn't create a model
w/ class for the Friend association, since I'm specifying className =>
'User'

I also tried the other approach - without having the UserFriend model,
also withouth the 'with' key of the association table, but dinamycally
binding the auto-with join model:
$this->User->UserFriend->bindModel(array('belongsTo' => array('User',
'Friend')));
I'm getting identical results as with modeling the join table.

I know this stuff has been extensively discussed, but I don't seem to
be able to grasp it in its entirety....

I'd be extremely thankful if anyone could hint me as to what I might
be doing wrong and what I need to change in my setup to achieve the
requirements specified above.

Thank you in advance!

Regards,
Nasko
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Cake 
PHP" group.
To post to this group, send email to cake-php@googlegroups.com
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