更加雄辩地定义多对多双向关系

时间:2016-08-27 22:27:23

标签: laravel eloquent

我已经实现了没有Eloquent的关系,但我想知道是否有一种方法可以在Eloquent中定义这种关系,以便我的应用程序可以更加一致。

table User
    -id
    -other user attributes

table friend_requests:
    -id
    -sender_id
    -reciever_id

table friends
    -id
    -first
    -second

在Eloquent中很容易实现friendRequest关系,但问题在于Friends。

如果我在User模型类中执行此操作:

public function friends(){
    return $this->belongsToMany(User::class,'friends','first','second');
}

这不会像你所注意到的那样起作用。让我用例子解释一下:

Table: friends 
 id    |   first    | second  
 1     |   1        | 2  
 2     |   3        | 1  

您发现user_1user_2以及user_3的朋友,因为这种关系是双向的。但Eloquent自然会返回user_1只有user_2的朋友。经过一段时间的思考后,我调整了陈述,但收效甚微

public function friends(){
    return $this->belongsToMany(User::class,'friends','first','second')
                ->orWhere('second',$this->id);
}

这是因为现在它选择了两行,但它返回的Userid = second的那些,这意味着在第二种情况下它将返回用户本身。 / p>

我在User模型类中使用我自己的方法实现了关系,使用DB::table('friends')->addFriend(User $user)removeFriend(user $user)并返回friends()的列表,但我和令人失望的是,这并不像Eloquent关系那样雄辩。

也许在这里有一些经验丰富的开发人员会遇到这样的问题,而且比我做得更好。你怎么建议我处理这个问题。我应该坚持我的方法还是有更好的方法来处理它?<​​/ p>

1 个答案:

答案 0 :(得分:2)

实现双向关系的一种更易于管理的方法是为每个确认的友谊创建两个条目。

因此,用户可以向其他用户发送朋友请求。当第二个用户确认好友请求时,会创建两个友谊。

示例控制器

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use App\FriendRequest;
use App\Friendship;

class FriendshipController extends Controller
{
    public function friendRequest(Request $request)
    {
        $receiver_id = $request->input('receiver_id');

        $request->user()->friend_offers()->create([
            'receiver_id' => $receiver_id
        ]);
    }

    public function friendshipConfirmation(Request $request)
    {
        $friend_request_id = $request->input('friend_request_id');

        $friend_request = FriendRequest::find($friend_request_id);

        $friend_request->receiver->friendships()->create([
            'user_2_id' => $friend_request->sender->id
        ]);

        $friend_request->sender->friendships()->create([
            'user_2_id' => $friend_request->receiver->id
        ]);
    }
}

数据库表

(注意receiver和复数users表的正确拼写)

table users
    - id
    - other user attributes

table friend_requests:
    - id
    - sender_id
    - receiver_id

table friendships
    - id
    - user_1_id
    - user_2_id

用户模型

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Authenticatable
{
    use SoftDeletes;

    public $timestamps = true;

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = ['created_at', 'updated_at', 'deleted_at'];

    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = ['id'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        //
    ];

    /**
     * Return friend requests from other users
     * 
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function friend_requests()
    {
        return $this->hasMany(FriendRequest::class, 'receiver_id');
    }

    /**
     * Return friend requests sent to other users
     * 
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function friend_offers()
    {
        return $this->hasMany(FriendRequest::class, 'sender_id');
    }

    /**
     * Return friendships with other users
     * 
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function friendships()
    {
        return $this->hasMany(Friendship::class, 'user_1_id');
    }
}

FriendRequest模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class FriendRequest extends Model
{
    use SoftDeletes;

    public $timestamps = true;

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = ['created_at', 'updated_at', 'deleted_at'];

    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = ['id'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'sender_id',
        'receiver_id'
    ];

    /**
     * Return the requesting user
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function sender()
    {
        return $this->belongsTo(User::class, 'sender_id');
    }

    /**
     * Return the receiving user
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function receiver()
    {
        return $this->belongsTo(User::class, 'receiver_id');
    }
}

友谊模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Friendship extends Model
{
    use SoftDeletes;

    public $timestamps = true;

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = ['created_at', 'updated_at', 'deleted_at'];

    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = ['id'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'user_1_id',
        'user_2_id'
    ];

    /**
     * Return user_1
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function first()
    {
        return $this->belongsTo(User::class, 'user_1_id');
    }

    /**
     * Return user_2
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function second()
    {
        return $this->belongsTo(User::class, 'user_2_id');
    }
}