我已经在没有 Eloquent 的情况下实现了这种关系,但我想知道是否有一种方法可以在 Eloquent 中定义这种关系,以便我的应用程序可以具有更高的一致性。
table User
-id
-other user attributes
table friend_requests:
-id
-sender_id
-reciever_id
table friends
-id
-first
-second
friendRequest 关系在 Eloquent 中很容易实现,但问题在于 Friends。
如果我在用户模型类中执行此操作:
public function friends(){
return $this->belongsToMany(User::class,'friends','first','second');
}
这不会像您所注意到的那样起作用。让我用例子来解释一下:
Table: friends
id | first | second
1 | 1 | 2
2 | 3 | 1
您会看到
user_1
与 user_2
以及 user_3
都是朋友,因为这种关系是双向的。但 Eloquent 自然会返回 user_1
只与 user_2
是朋友。经过思考一段时间,我调整了声明,但进展甚微'
public function friends(){
return $this->belongsToMany(User::class,'friends','first','second')
->orWhere('second',$this->id);
}
那是因为现在它选择了两行,但它返回的
User
是那些 id
= second
的行,这意味着在第二种情况下它将返回用户本身。
我在
User
模型类中实现了我自己的方法的关系,该模型类使用DB::table('friends')->
到addFriend(User $user)
,removeFriend(user $user)
并返回friends()
列表,但我很失望,这不像那么雄辩Eloquent
关系。
也许这里一些更有经验的开发人员会遇到这种问题,并且会比我处理得更好。你建议我如何处理这个问题。我应该坚持我的方法还是有更好的方法来处理它?
实现双向关系的更易于管理的方法是为每个已确认的友谊创建两个条目。
因此,一个用户会向另一个用户发出好友请求。当第二个用户确认好友请求时,就会创建两个好友。
<?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');
}
}
<?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');
}
}
我通过 union
morphToMany()
和 morphedByMany()
获得了双向关系,并使用了一些解决方法,如下所述:https://github.com/laravel/framework/discussions/50302