php - tabla - Sistema de amistad con Laravel: relación Muchos a Muchos.
relación muchos a muchos eloquent (2)
Estoy tratando de crear un sistema de amistad con Laravel (estoy empezando por eso) pero estoy bloqueado con las relaciones. Aquí está la cosa: hay una tabla Usuarios y una tabla Amigos que contiene las siguientes columnas:
friends: id, user_id, friend_id, accepted.
Parece mucho a muchos, así que esto es lo que configuré en la clase de usuario:
class User extends Eloquent {
function friends()
{
return $this->belongsToMany(''User'');
}
}
Pero cuando intento un:
$friends = User::find($id)->friends()->get()
Tengo este error:
Base table or view not found: 1146 Table ''base.user_user'' doesn''t exist
Me gustaría obtener una lista de los Amigos de un usuario, no importa si el usuario envió la invitación o la recibió. Así que el usuario puede ir en user_id o friend_id y luego recupero los datos del otro usuario dependiendo de esa columna.
¿Alguna idea? ¡Gracias!
EDITAR: Aquí está el código que utilizo:
$usersWithFriends = User::with(''friendsOfMine'', ''friendOf'')->get();
$user = User::find(Auth::id())->friends;
foreach($user as $item) {
echo $item->first()->pivot->accepted;
}
tldr; necesita 2 relaciones invertidas para que funcione, verifique CONFIGURACIÓN y USO a continuación
Primero, el error : así es como debería verse tu relación:
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);
}
Entonces funcionará sin errores:
$user->friends; // collection of User models, returns the same as:
$user->friends()->get();
PREPARAR
Sin embargo , le gustaría que la relación funcione en ambos sentidos. Eloquent no proporciona una relación de ese tipo, por lo que puede utilizar 2 relaciones invertidas y combinar los resultados :
// 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);
}
USO
Con tal configuración puedes hacer esto:
// 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;
Es un problema en su base de datos y también la definición de la relación. El tipo de relación Many-to-Many espera que use una tabla intermedia. Esto es lo que tienes que hacer:
- Cree una
user_friend (id, user_id, fried_id)
en su esquema. - Eliminar campos innecesarios de
user
tablas deuser
yfriend
. - Crear claves externas adecuadas.
user.id
->user_friend.user_id
,friend.id
->user_friend.friend_id
- Mejor definir la relación completa en los modelos de Usuario y Amigo ,
por ejemplo :
class User extends Eloquent {
function friends()
{
return $this->belongsToMany(''User'', ''user_friend'', ''user_id'', ''friend_id'');
}
}
Puedes leer mucho más en los documentos de Laravel, HERE