Mysql
 sql >> Base de données >  >> RDS >> Mysql

laravel éloquent trier par relation

À ma connaissance, charge ardente with méthode exécuter la 2ème requête. C'est pourquoi vous ne pouvez pas obtenir ce que vous voulez avec le chargement rapide with méthode.

Je pense utiliser join méthode en combinaison avec la méthode relationnelle est la solution. La solution suivante a été entièrement testée et fonctionne bien.

// In User Model
public function channels()
{
    return $this->belongsToMany('App\Channel', 'channel_user')
        ->withPivot('is_approved');
}

public function sortedChannels($orderBy)
{
    return $this->channels()
            ->join('replies', 'replies.channel_id', '=', 'channel.id')
            ->orderBy('replies.created_at', $orderBy)
            ->get();
}

Ensuite, vous pouvez appeler $user->sortedChannels('desc') pour obtenir la liste des chaînes trier par réponses created_at attribut.

Pour des conditions telles que chaînes (qui peut ou non avoir des réponses), utilisez simplement leftJoin méthode.

public function sortedChannels($orderBy)
    {
        return $this->channels()
                ->leftJoin('replies', 'channel.id', '=', 'replies.channel_id')
                ->orderBy('replies.created_at', $orderBy)
                ->get();
    }

Modifier :

Si vous souhaitez ajouter groupBy méthode à la requête, vous devez porter une attention particulière à votre orderBy clause. Parce qu'en Sql nature, Group By clause exécutée en premier avant Order By clause. Voir le détail de ce problème sur cette question de débordement de pile .

Donc, si vous ajoutez groupBy méthode, vous devez utiliser orderByRaw méthode et doit être implémenté comme suit.

return $this->channels()
                ->leftJoin('replies', 'channels.id', '=', 'replies.channel_id')
                ->groupBy(['channels.id'])
                ->orderByRaw('max(replies.created_at) desc')
                ->get();