2

在我的 CakePHP 应用程序中,我的用户能够与其他用户成为朋友。

这是通过一个users表和一个friends_users具有以下列的表来完成的:id, user_id, friend_id, status用于关系。

因此,如果用户 id 1 是用户 id 2 的朋友,则 user_id 中将有 1,friend_id 列中将有 2

User 的模型如下所示:

public $hasAndBelongsToMany = array(
        'Friend'=>array(
            'className'              => 'User',
            'joinTable'              => 'friends_users',
            'foreignKey'             => 'user_id',
            'associationForeignKey'  => 'friend_id'
        )
    );

查看用户 1 时,它工作正常并将用户 2 显示为朋友。但是在查看用户 2 时,它并没有将用户 1 显示为朋友......所以当反向查看时,它并没有填满数据!

这是我用来为用户列出朋友的方法:

$user = $this->User->find('first', array( 
                    'conditions' => array('User.id' => $this->Auth->user('id')),
                    'contain'=>'Profile'
                ));

        $friends = $this->User->find('first', 
            array(
                'conditions'=>array(
                   'User.id'=>$user['User']['id']
                ),
                'contain'=>array(
                    'Profile',
                    'Friend'=>array(
                        'Profile',
                        'conditions'=>array(
                            'FriendsUser.status'=>1
                        )
                    )
                )
            )
        );

        $this->set('friends', $friends);

任何想法为什么会发生这种情况?我浏览了文档,但对我来说一切都很好。

理想情况下,我想修复我的代码,而不是指向其他资源!

页面查询:http: //pastebin.com/zQnBVM2X

4

2 回答 2

2

当您检索用户#6 的朋友时,您将获得朋友#8。当您检索用户 #8 的朋友时,您应该什么也没有收到,因为您的friends_users表中没有用户 #8 的记录。因此,您需要在friends_users表 ( user_id = 8, friend_id = 6) 中插入其他数据,或者您需要创建Friend模型(不使用表)并通过Friend. 那是心理体操——你需要意识到用户是朋友,朋友是用户。

        $friends = $this->User->Friend->find('first', 
            array(
                'conditions'=>array(
                   'Friend.id'=>$id // user id whose friends you need to find
                ),
                'contain'=>array(
                    'Profile',
                    'User'=>array( // here you will get friends
                        'Profile',
                        'conditions'=>array(
                            'FriendsUser.status'=>1
                        )
                    )
                )
            )
        );
于 2012-09-26T23:16:47.727 回答
0

这是一个有趣的问题,几年前我在建立一个约会网站时也遇到了同样的问题。

您需要做的是(在我的情况下)有 4 组关系:

  • 前向关系
  • 转发关系(未经批准的友谊)
  • 后向关系
  • 落后的关系(未经批准的友谊)

这将确保您提取所有必要的数据,containable尽可能使用。

var $hasAndBelongsToMany = array(
    'ForwardRelation' => array(
        'className'  => 'User',
        'joinTable'  => 'friends_users',
        'foreignKey' => 'user_id',
        'conditions' => array('approved' => '1'),
        'associationForeignKey' => 'friend_id',
        ),
    'ForwardRelationUn' => array(
       'className'  => 'User',
        'joinTable'  => 'friends_users',
        'foreignKey' => 'user_id',
        'conditions' => array('approved' => '0'),
        'associationForeignKey' => 'friend_id'
        ),
    'BackRelation' => array(
        'className'  => 'User',
        'joinTable'  => 'friends_users',
        'foreignKey' => 'friend_id',
        'associationForeignKey' => 'user_id',
        'conditions' => array('approved' => 1)
        ),
    'BackRelationUn' => array(
        'className'  => 'User',
        'joinTable'  => 'friends_users',
        'foreignKey' => 'friend_id',
        'associationForeignKey' => 'user_id',
        'conditions' => array('approved' => '0')
    )
);

添加一个带有一些afterFind()魔法的行为,你会是金色的!

这是我寻找朋友的功能:

function getFriends( $userid, $search = null ) {

    $Friends    = ClassRegistry::init( 'FriendsUser' );

    $Friends->bindModel( 
        array(
            'belongsTo' => array(
                'User' => array(
                    'className' => 'User',
                    'foreignKey' => 'user_id'
                ),
                'Friend' => array(
                    'className' => 'User',
                    'foreignKey' => 'friend_id'
                    )
                )
            )
        );

    $data = $Friends->find( 
        'all', 
        array( 
            'fields' => array( 
                'DISTINCT FriendsUser.friend_id', 
                'FriendsUser.user_id',
                'FriendsUser.approved',
                'User.id', 
                'User.username', 
                'Friend.id', 
                'Friend.username'
                ), 
            'conditions' => array(
                 'AND' => array(
                     'OR' => array( 
                        'Friend.username LIKE' => '%' . $search . '%',
                        'User.username LIKE' => '%' . $search . '%'
                        )
                    )
                ),
            'contain' => array(
                'User', 
                'Friend'
                ),
            'order' => array( 'User.username ASC', 'FriendsUser.approved DESC' )
        ) 
    );


    $friendlist = array();
    $i = 0;

    foreach ( $data as $datum ) {

        foreach ( $datum as $key => $value ) {

            if ( in_array( $key, array( 'User', 'Friend' ) ) ) {

                if ( $value['id'] == $userid ) {
                    $friendlist[$i]['Me'] = $value;
                } else {
                    $friendlist[$i]['Friend']           = $value;
                }

            }
        }

        $i++;

    }

    $matches = array();

    foreach ( $friendlist as $friend ) {

        if ( stripos( $friend['Friend']['username'], $search ) !== false )
            $matches[ $friend['Friend']['id'] ] = $friend['Friend']['username'];

    }

    asort( $matches );

    $i = 0;

    $newmatches = array();

    foreach ( $matches as $key => $match ) {
        $newmatches[$i]['Tag']['caption']   = $match;
        $newmatches[$i]['Tag']['value']     = $key; 
        $newmatches[$i]['Tag']['image']     = $this->getProfileImage( $key );

        $i++;       
    }

    return $newmatches;

}
于 2012-09-26T23:07:21.660 回答