نظام الصداقة مع Laravel :كثير إلى كثير العلاقة
سؤال
أحاول إنشاء نظام صداقة باستخدام Laravel (بدأت به) ولكني محظور بالعلاقات.هنا الحاجة :يوجد جدول واحد للمستخدمين وجدول واحد للأصدقاء يحتوي على الأعمدة التالية:
friends: id, user_id, friend_id, accepted.
يبدو الأمر من كثير إلى كثير، لذا إليك ما قمت بتعيينه في فئة المستخدم:
class User extends Eloquent {
function friends()
{
return $this->belongsToMany('User');
}
}
ولكن عندما أحاول:
$friends = User::find($id)->friends()->get()
لدي هذا الخطأ :
Base table or view not found: 1146 Table 'base.user_user' doesn't exist
أرغب في الحصول على قائمة بأصدقاء المستخدم، بغض النظر عما إذا كان المستخدم قد أرسل الدعوة أو استلمها.لذلك يمكن للمستخدم استخدام user_id أو friends_id ثم استرداد بيانات المستخدم الآخر اعتمادًا على هذا العمود.
اي فكرة؟شكرًا!
يحرر :إليك الرمز الذي أستخدمه:
$usersWithFriends = User::with('friendsOfMine', 'friendOf')->get();
$user = User::find(Auth::id())->friends;
foreach($user as $item) {
echo $item->first()->pivot->accepted;
}
المحلول
تلدر؛أنت بحاجة إلى علاقتين مقلوبتين حتى تنجح، تحقق من الإعداد والاستخدام أدناه
أولا قبالة خطأ - هكذا يجب أن تبدو علاقتكما:
function friends()
{
return $this->belongsToMany('User', 'friends', 'user_id', 'friend_id')
// if you want to rely on accepted field, then add this:
->wherePivot('accepted', '=', 1);
}
وبعد ذلك سوف يعمل بدون أخطاء:
$user->friends; // collection of User models, returns the same as:
$user->friends()->get();
يثبت
لكن ترغب في أن تعمل العلاقة في كلا الاتجاهين.Eloquent لا يقدم علاقة من هذا النوع، لذلك يمكنك بدلاً من ذلك استخدام علاقتين مقلوبتين ودمج النتائج:
// friendship that I started
function friendsOfMine()
{
return $this->belongsToMany('User', 'friends', 'user_id', 'friend_id')
->wherePivot('accepted', '=', 1) // to filter only accepted
->withPivot('accepted'); // or to fetch accepted value
}
// friendship that I was invited to
function friendOf()
{
return $this->belongsToMany('User', 'friends', 'friend_id', 'user_id')
->wherePivot('accepted', '=', 1)
->withPivot('accepted');
}
// accessor allowing you call $user->friends
public function getFriendsAttribute()
{
if ( ! array_key_exists('friends', $this->relations)) $this->loadFriends();
return $this->getRelation('friends');
}
protected function loadFriends()
{
if ( ! array_key_exists('friends', $this->relations))
{
$friends = $this->mergeFriends();
$this->setRelation('friends', $friends);
}
}
protected function mergeFriends()
{
return $this->friendsOfMine->merge($this->friendOf);
}
الاستخدام
مع هذا الإعداد يمكنك القيام بذلك:
// access all friends
$user->friends; // collection of unique User model instances
// access friends a user invited
$user->friendsOfMine; // collection
// access friends that a user was invited by
$user->friendOf; // collection
// and eager load all friends with 2 queries
$usersWithFriends = User::with('friendsOfMine', 'friendOf')->get();
// then
$users->first()->friends; // collection
// Check the accepted value:
$user->friends->first()->pivot->accepted;
نصائح أخرى
إنها مشكلة واضحة في قاعدة البيانات الخاصة بك وأيضًا تعريف العلاقة.يتوقع منك نوع العلاقة متعدد إلى متعدد أن تستخدمه وجدولًا متوسطًا.إليك ما عليك فعله:
- إنشاء
user_friend (id, user_id, fried_id)
الجدول في المخطط الخاص بك. - قم بإزالة الحقول غير الضرورية من
user
وfriend
الجداول. - إنشاء مفاتيح خارجية مناسبة.
user.id
->user_friend.user_id
,friend.id
->user_friend.friend_id
- من الأفضل تحديد العلاقة الكاملة على مستخدم و صديق عارضات ازياء،
على سبيل المثال :
class User extends Eloquent {
function friends()
{
return $this->belongsToMany('User', 'user_friend', 'user_id', 'friend_id');
}
}
يمكنك قراءة المزيد في مستندات Laravel، هنا