Pregunta

Estoy intentando crear un sistema de Amistad con Laravel (estoy empezando con él) 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 de muchos a muchos, así que esto es lo que configuré en la clase 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, sin importar si el usuario envió la invitación o la recibió.Entonces, el usuario puede basarse en user_id o en friend_id y luego recupero los datos del otro usuario dependiendo de esa columna.

¿Alguna idea?¡Gracias!

EDITAR :Aquí está el código que uso:

$usersWithFriends = User::with('friendsOfMine', 'friendOf')->get();
$user = User::find(Auth::id())->friends;

foreach($user as $item) {
    echo $item->first()->pivot->accepted;
} 
¿Fue útil?

Solución

TLDR;Necesita 2 relaciones invertidas para que funcione, verifique la configuración y el uso a continuación


primero del error - Así es como debe parecer su 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();


Configuración

Sin embargo le gustaría que la relación funcione en ambos sentidos.Elocuentes no proporciona una relación de ese tipo, por lo que puede usar 2 relaciones invertidas y fusionar 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, puede 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;

Otros consejos

Obviamente es un problema en su base de datos y también en la definición de la relación.El tipo de relación de muchos a muchos espera que utilice una tabla intermedia.Esto es lo que tienes que hacer:

  1. Crear un user_friend (id, user_id, fried_id) tabla en su esquema.
  2. Eliminar campos innecesarios de user y friend mesas.
  3. Cree claves foráneas adecuadas. user.id-> user_friend.user_id , friend.id -> user_friend.friend_id
  4. Definir mejor la relación completa en el Usuario y Amigo modelos,

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, AQUÍ

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top