11 votes

Comment utiliser "group by" avec une relation polymorphe dans Laravel ?

J'ai la relation suivante :

return $this->morphedByMany('App\Models\Movie', 'listable', 'cnt_lists', 'list_id')->withPivot('id', 'order', 'updated_at')->where('movies.has_poster', true)->orderBy('order', 'desc')->withTimestamps();

Cette relation produit cette requête :

select `movies`.*, `cnt_lists`.`list_id` as `pivot_list_id`, `cnt_lists`.`listable_id` as `pivot_listable_id`, `cnt_lists`.`id` as `pivot_id`, `cnt_lists`.`order` as `pivot_order`, `cnt_lists`.`updated_at` as `pivot_updated_at`, `cnt_lists`.`created_at` as `pivot_created_at` from `movies` inner join `cnt_lists` on `movies`.`id` = `cnt_lists`.`listable_id` where `movies`.`has_poster` = '1' and `cnt_lists`.`list_id` in ('3176', '3283', '3285', '3287') and `cnt_lists`.`listable_type` = 'App\Models\Movie' order by `order` desc

Cette relation fonctionne, mais elle en prend beaucoup pour chaque liste. J'essaie de limiter à un seul par liste. À l'origine, j'explorais take() mais cela limite l'ensemble des résultats, pas une limite par liste. J'ai alors pensé que je pourrais regrouper par le cnt_lists.list_id qui en prendrait un par liste. Cela semble me permettre d'obtenir ce que je recherche. J'essaie simplement de comprendre comment utiliser le groupe par dans la relation, car cela casse la relation lorsque je l'ajoute.

select `movies`.*, `cnt_lists`.`list_id` as `pivot_list_id`, `cnt_lists`.`listable_id` as `pivot_listable_id`, `cnt_lists`.`id` as `pivot_id`, `cnt_lists`.`order` as `pivot_order`, `cnt_lists`.`updated_at` as `pivot_updated_at`, `cnt_lists`.`created_at` as `pivot_created_at` from `movies` inner join `cnt_lists` on `movies`.`id` = `cnt_lists`.`listable_id` where `movies`.`has_poster` = '1' and `cnt_lists`.`list_id` in ('3176', '3283', '3285', '3287') and `cnt_lists`.`listable_type` = 'App\Models\Movie' group by `cnt_lists`.`list_id` order by `order` desc

Quand j'ajoute groupBy dans la relation :

return $this->morphedByMany('App\Models\Movie', 'listable', 'cnt_lists', 'list_id')->withPivot('id', 'order', 'updated_at')->where('movies.has_poster', true)->groupBy('cnt_lists.list_id')->orderBy('order', 'desc')->withTimestamps();

Je reçois l'erreur suivante :

select `movies`.*, `cnt_lists`.`list_id` as `pivot_list_id`, `cnt_lists`.`listable_id` as `pivot_listable_id`, `cnt_lists`.`id` as `pivot_id`, `cnt_lists`.`order` as `pivot_order`, `cnt_lists`.`updated_at` as `pivot_updated_at`, `cnt_lists`.`created_at` as `pivot_created_at` from `movies` inner join `cnt_lists` on `movies`.`id` = `cnt_lists`.`listable_id` where `movies`.`has_poster` = 1 and `cnt_lists`.`list_id` in (3176, 3283, 3285, 3287) and `cnt_lists`.`listable_type` = App\Models\Movie group by `cnt_lists`.`list_id` order by `order` desc

Pour une raison quelconque, le modèle App\Models\Movie n'est pas entre guillemets, ce qui casse toute la requête. Si j'exécute la requête manuellement, elle fonctionne, je dois juste ajouter des guillemets au modèle polymorphe, à savoir "App\Models\Movie"

2voto

ATLChris Points 1340

Ok, il s'avère donc que le problème était lié au mode strict de MySQL, qui inclut ONLY_FULL_GROUP_BY mode.

J'ai désactivé le mode strict au niveau de Laravel et la requête fonctionne maintenant comme prévu. Il suffit de mettre strict à false dans le fichier de configuration de la base de données pour votre connexion.

'strict' => false,

2voto

Kumar Rakesh Points 2270

J'ai reçu votre question et votre réponse. D'après votre réponse, je comprends que le problème principal est le "mode strict", qui n'est en fait que la liste des modes que 5.7 active par défaut. Parfois, nos collaborateurs ne comprennent pas bien strict mode . Sur https://mattstauffer.co/blog/strict-mode-and-other-mysql-customizations-in-laravel-5-2 ce lien, vous apprendrez comment Enabling and disabling strict mode in Laravel 5.2 Par exemple

Ces paramètres se trouvent dans config/database.php, dans la section connections.mysql. Pour commencer, voyons comment activer et désactiver le mode "strict" :

 'connections' => [
        'mysql' => [
            // Behave like MySQL 5.6
            'strict' => false,

            // Behave like MySQL 5.7
            'strict' => true,
        ]
    ]

Nous pouvons également le personnaliser par :

'connections' => [
        'mysql' => [
            // Ignore this key and rely on the strict key
            'modes' => null,

            // Explicitly disable all modes, overriding strict setting
            'modes' => [],

            // Explicitly enable specific modes, overriding strict setting
            'modes' => [
                'STRICT_TRANS_TABLES',
                'ONLY_FULL_GROUP_BY',
            ],
        ]
    ]

Merci

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X