Bonjour à tous,

Je galère un peu à obtenir le résultat que je souhaite avec les relations Laravel...
Je m'explique, je cherche à fire une sorte de bulltein appel journalier pour les utilisateurs de l'appli. Pour ce faire j'ai 3 tables :
users, status, status_user

Ma table status_user comporte 3 colonnes : status_id, user_id, status_date.
Je stock la date de saisie sur ma table pivot pour historiser les jours de présence.

Dans mon model User j'ai créé cette relation avec ce scope :

    public function attendance()
    {
        return $this->belongsToMany(Status::class, 'pm_status_user', 'user_id', 'status_id')
            ->withPivot( ['status_id', 'user_id', 'status_date'] )
            ->orderBy('status_date', 'asc');
    }

    public function scopeDate($query, $date)
    {
        return $query->whereHas('attendance', function ($q) use($date){
            $q->where('status_date', $date);
        });
    }

Ce que je cherche à obtenir, c'est de récuperer le statut de présence pour x utilisateur pour le jour donné.

$user = User::find(1)->date(Carbon::now())->get;
dd($user->attendance->name)); // devrait me renvoyer mon statut pour aujourd'hui, hors je récupère null

Je cherche également à pourvoir mettre à jour ce statut de la manière suivante :

$user = User::findOrFail(1);
$user->attendance->sync($request->all());

Si vous avez une solutions et/ou piste pour m'aiguiller ce serait sympa.

Merci :)

1 réponse


Azorgh
Réponse acceptée

Salut,

Dans un premier temps je dirais que ta relation est mal définie. En effet, les propriétés "pivot" sont seulement celles en sus. Donc ->withPivot( ['status_id', 'user_id', 'status_date'] ) devient ->withPivot( ['status_date'] ).

Ensuite, au niveau de ta requête et de ton scope, tu cherches à récupérer seulement les User qui ont au moins un Statut sur la date donnée.
En réalité tu ne filtre pas les résultats de la relation, mais il s'agit juste ici d'une condition. (Il faut que l'utilisateur ai au moins un statut sur la date donnée).

Ensuite, un BelongsToMany doit te retourner une collection (de Status dans ton cas) et non un seul objet. Tu ne devrais donc pas pouvoir faire

$user->attendance->name

Par contre, ca oui :

$user->attendance->first()->name;
$user->attendance->first()->pivot->status_date;

Pour ta méthode sync(), il faut que ce soit un tableau, avec en clé, l'ID du statut concerné, et en valeur, les valeurs pivots.
Exemple :

$data = [
    1 => ['status_date' => '2019-05-24'],
    2 => ['status_date' => '2019-05-23']
];

$user = User::findOrFail(1);
$user->attendance->sync($data);

J'ai écris un peu en même temps que je réfléchissais, j'espère avoir été clair et avoir pu te donner quelques pistes :)