web-dev-qa-db-fra.com

SQLSTATE [42000]: erreur de syntaxe ou violation d'accès: 1066 table / alias non unique sur la relation

Donc, je reçois l'erreur suivante de Laravel framework; mais je n'ai pas pu trouver pourquoi ce framework produit cette erreur:

SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'participants' (SQL: select `participants`.*, `participants`.`message_id` as `pivot_message_id`, `participants`.`user_id` as `pivot_user_id`, `participants`.`created_at` as `pivot_created_at`, `participants`.`updated_at` as `pivot_updated_at` from `participants` inner join `participants` on `participants`.`id` = `participants`.`user_id` where `participants`.`deleted_at` is null and `participants`.`message_id` in (2))

Ma relation message/participants ressemble à ceci:

public function participants()
{
    return $this->belongsToMany('Namespace\Modules\Email\Models\Participant', 'participants', 'message_id', 'user_id')->withTimestamps();
}

et j'essaie de l'appeler comme ceci:

public function getAllMessages()
{
   return Message::with('user')->with('participants')->get();
}

Pourquoi ai-je cette erreur? Que se passe-t-il?

Modifier: modèles complets inclus

Message

class Message extends Eloquent
{
    use PublishedTrait;
    use SoftDeletingTrait;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'messages';

    /**
     * The attributes that can be set with Mass Assignment.
     *
     * @var array
     */
    protected $fillable = ['subject', 'user_id', 'body', 'status'];

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

    /**
     * Validation rules.
     *
     * @var array
     */
    protected $rules = [
        'subject' => 'required|max:255',
        'body' => 'required',
    ];

    /**
     * User relationship
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(Config::get('email.user_model'));
    }

    public function assets()
    {
        return $this->belongsToMany('Namespace\Modules\Assets\Models\Asset', 'message_assets');
    }

    /**
     * Participants relationship
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function participants()
    {
        return $this->belongsToMany('Namespace\Modules\Email\Models\Participant', 'participants', 'message_id', 'user_id')->withTimestamps();
    }

    /**
     * Recipients of this message
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function recipients()
    {
        return $this->participants()->where('user_id', '!=', $this->user_id);
    }

    /**
     * Returns the latest message from a thread
     *
     * @return Namespace\Modules\Email\Models\Message
     */
    public function getLatestMessageAttribute()
    {
        return $this->messages()->latest()->first();
    }

    /**
     * Returns threads that the user is associated with
     * @param $query
     * @param $userId
     * @return mixed
     */
    public function scopeForUser($query, $userId)
    {
        return $query->join('participants', 'messages.id', '=', 'participants.message_id')
            ->where('participants.user_id', $userId)
            ->where('participants.deleted_at', null)
            ->select('messages.*');
    }

    /**
     * Returns threads that the user is associated with
     * @param $query
     * @param $userId
     * @return mixed
     */
    public function scopeForUserWithDeleted($query, $userId)
    {
        return $query->join('participants', 'messages.id', '=', 'participants.message_id')
            ->where('participants.user_id', $userId)
            ->select('messages.*');
    }

    /**
     * Returns messages that the user has sent
     * @param $query
     * @param $userId
     * @return mixed
     */
    public function scopeByUser($query, $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * Returns threads with new messages that the user is associated with
     * @param $query
     * @param $userId
     * @return mixed
     */
    public function scopeForUserWithNewMessages($query, $userId)
    {
        return $query->join('participants', 'messages.id', '=', 'participants.message_id')
            ->where('participants.user_id', $userId)
            ->whereNull('participants.deleted_at')
            ->where(function ($query) {
                $query->where('messages.updated_at', '>', $this->getConnection()->raw($this->getConnection()->getTablePrefix() . 'participants.last_read'))
                    ->orWhereNull('participants.last_read');
            })
            ->select('messages.*');
    }

}

Participant

class Participant extends Eloquent
{
    use SoftDeletingTrait;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'participants';

    /**
     * The attributes that can be set with Mass Assignment.
     *
     * @var array
     */
    protected $fillable = ['message_id', 'user_id', 'last_read'];

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

    /**
     * Thread relationship
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function message()
    {
        return $this->hasMany('Namespace\Modules\Email\Models\Message');
    }

    /**
     * User relationship
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(Config::get('email.user_model'));
    }
}
12
ChrisBratherton

Répondu via le Slack officiel de Larachat:

Il manque à la relation un tableau croisé dynamique pour que cela fonctionne. Le deuxième argument de la méthode participants est le tableau croisé dynamique à utiliser:

public function participants()
{
    return $this->belongsToMany('Namespace\Modules\Email\Models\Participant', 'PIVOT', 'message_id', 'user_id')->withTimestamps();
}

Par conséquent, vous ne pouvez pas utiliser les participants comme pivot, car il s'agit de l'une des tables de la relation, vous avez besoin d'un message_participant tableau croisé dynamique.

8
Jamesking56

Votre erreur est

...from `participants` inner join `participants` ...

Vous devez fournir des alias pour chaque référence, comme dans

...from `participants` p1 inner join `participants` p2 ...

puis utilisez p1 et p2 aux bons endroits, par exemple

...on p1.`id` = p2.`user_id` ...

(Je suppose que c'est p1 et qui est p2; vous devez faire cette détermination)

2
Jim Garrison

Répondre à cette question pour toute personne ayant rencontré cette erreur beaucoup plus tard.

A en juger par vos enregistrements de table, le participants table semble être le pivot table entre users et messages. Vous faites référence au tableau croisé dynamique, ce qui entraîne un mauvais comportement de la base de données.

La bonne façon de procéder est dans vos modèles users:

public function messages(){
   return $this->belongsToMany(Message::class, 'participants', 'user_id', 'message_id')->withPivot('last_read');
}

Dans vos modèles messages:

public function users(){
   return $this->belongsToMany(User::class, 'participants', 'message_id', 'user_id')->withPivot('last_read');
}

De cette façon, lorsque vous appelez des messages d'utilisateurs, utilisez ceci:

$messages = $user->messages()->get();

Et lorsque vous vérifiez les utilisateurs pour le message,

$user = $message->users()->get()

Et dernière lecture

$last_read = $message->pivot->last_read;
0
AntonyMN