OctoberCMS: How to maintain a two-way friendship relation?

不打扰是莪最后的温柔 提交于 2019-12-24 06:03:04

问题


I'm extending the rainlab.user plugin to allow each user to have friends via a simple intermediate table with the following fields:

user_id
friend_id
status

I've extended the User model:

use RainLab\User\Models\User as FrontUser;

FrontUser::extend(function($model) {

    $model->belongsToMany['friends']=[
        'RainLab\User\Models\User',
        'table'    => 'meysam_social_friends',
        'pivot' => ['status'],
        'pivotModel' => 'Meysam\Social\Models\FriendsPivot',
        'timestamps' => true,
        'key'      => 'user_id',
        'otherKey' => 'friend_id'
    ];

    $model->addDynamicMethod('isFriendWith', function (FrontUser $user) use ($model) {
        $model->friends->contains($user->id);
    });

    $model->addDynamicMethod('addFriend', function (FrontUser $user) use ($model) {
        $model->friends()->attach($user->id);
    });

    $model->addDynamicMethod('removeFriend', function (FrontUser $user) use ($model) {
        $model->friends()->detach($user->id);
    });
});

And also extended the Rainlab.User Controller to have Friends tab where all friends of a user are listed and can be added and removed:

use RainLab\User\Controllers\Users as UsersController;

UsersController::extend(function($controller) {

    if(!isset($controller->implement['Backend.Behaviors.RelationController'])) {
        $controller->implement[] = 'Backend.Behaviors.RelationController';
    }
    $controller->relationConfig  =  '$/meysam/social/controllers/user/config_relations.yaml';
});

UsersController::extendFormFields(function($form, $model, $context) {
    if(!$model instanceof FrontUser or $context != 'preview'){
        // friends tab should not be displayed in update and create contexts
        return;
    }

    $form->addTabFields([
        'friends' => [
            'label' => '',
            'tab' => 'Friends',
            'type' => 'partial',
            'path' => '$/meysam/social/controllers/user/_friends.htm',
        ]
    ]);
});

Now I need to maintain a two-way friendship relationship. i.e. whenever user_id and friend_id is added to the friends table, I want to automatically add friend_id and user_id to the table as well. To achieve this, I implemented afterSave and beforeSave in the FriendsPivot model:

class FriendsPivot extends Pivot
{
    /*
     * Validation
     */
    public $rules = [
        'status' => 'required'
    ];

    public $belongsTo = [
        'user' => ['RainLab\User\Models\User', 'key' => 'user_id'],
        'friend' => ['RainLab\User\Models\User', 'key' => 'friend_id']
    ];

    public function getStatusOptions()
    {
        return [
            1 => 'Pending',
            2 => 'Approved',
            3 => 'Blocked',
        ];
    }

    public function afterSave()
    {
        Log::info('Saving pivot...');

        if(!$this->friend->isFriendWith($this->user)) {
            $this->friend->addFriend($this->user);
        }
    }

    public function beforeDelete()
    {
        Log::info('Deleting pivot...');

        if($this->friend->isFriendWith($this->user)) {
            $this->friend->removeFriend($this->user);
        }
    }
}

The problem is that beforeDelete is never called. afterSave gets called but beforeDelete never gets called and therefor the inverse of the relationship is not deleted (user_id-friend_id gets removed from database but friend_id-user_id does not get deleted). Why is beforeDelete not called? Is there anything I'm doing wrong? Is there any better way to maintain a two-way friendship relation?


回答1:


I found this post because I'm trying to do exactly the same thing as you. If you have solved this then I wonder if you would be willing to share your solution?




回答2:


This sounds very odd at first, but maybe this is because of the special delete behavior of the Pivot model. It appears that it builds a raw query using the QueryBuilder and thus bypasses any regular Eloquent (October) events. In my eyes, the best solution would be to trigger the delete event manually in the delete method, but I'm unsure if this has any side effects. Maybe you could test that and prepare a PR on Github if it works.



来源:https://stackoverflow.com/questions/42740344/octobercms-how-to-maintain-a-two-way-friendship-relation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!