Bonjour à tous,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Je récupère en bdd une liste de sites.

public function index(){

        $websites = Website::paginate(10);

        return view('List.index')->with(
            [
                'websites'=>$websites            
            ]
        );
    }

Ce que je veux

Je souhaiterai trier ces sites en fonction de leurs nombre de votes.
Pour le système de vote, j'utilise [https://github.com/jcc/laravel-vote].
Ce package propose bien une méthode pour compter les votes d'une entité ('countUpVoters()') mais je ne sais pas comment l'utiliser avec un OrderBy par exemple.

Ce que j'obtiens

J'ai essayé quelque chose comme ça, mais sans étonnement cela ne fonctionne pas.

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'countUpVoters' in 'order clause' (SQL: select from websites order by countUpVoters desc limit 10 offset 0)*

$websites = Website::orderBy('countUpVoters', 'desc')
            ->paginate(10);

Ou bien

$websites = Website::paginate(10);

$websites->sortBy('countUpVoters');

Avec comme erreur: App\Website::countUpVoters must return a relationship instance.

Je ne sais pas si cela est compliqué à mettre en place mais je débute avec Laravel, merci d'être indulgent :) .

J'espère que quelqu'un pourra m'aider, merci d'avoir lu.

Luzzbe

8 réponses


Amilti
Réponse acceptée

Sinon tu as une autre solution qui peut être intéressante, tu pourrais créer un champ nb_votes qui vaudra 0 par défaut dans ta table websites et ensuite créer un observer pour ta classe Vote .
https://laravel.com/docs/5.5/eloquent#observers

et à chaque foit que tu crées un vote pour un site tu enregistres la valeur de countUpVoters(); dans le champ nb_votes et comme ça tu pourra faire directement :

Website::orderBy('nb_votes', 'desc')
            ->paginate(10);

Cette solution à l'avantage de faire une requête moins gourmande quand tu veux récuperer ta liste de website

Hello,
Hum, pour régler ton probléme rapidemment (je connais pas le package en question donc je ne sais pas trop ce qu'il fait) .
Mais tu pourrais créer un mutator dans ta class website:

 public function getNbVoteAttribute()
{
        return $this->countUpVoters();
}
$websites = Website::paginate(10);
$websites->sortBy('nb_vote');

https://laravel.com/docs/5.5/eloquent-mutators

à noter que les mutators ne fonctionnent pas sur les query builder, tu peux les gérer uniquement sur des collections .
Je sais plus si paginate retourne une collection donc à tester ^^ .

Après si tu veux une autre solution je pense qu'il faudra que tu passes par une requête sql entre ta table website et vote .

luzzbe
Auteur

@Amilti: Merci pour ton aide. J'ai essayé de créer un mutator mais une fois celui-ci mis en place avec mon sortBy (comme dans ton exemple), je n'ai plus accès à ma méthode links ($website->links) pour ma pagination.
Method links does not exist.

$websites = Website::paginate(10)->sortByDesc('nb_vote');

Y a-t-il une autre possibilité pour mettre en place ce genre de requête ?

Edit: (Je regarde du coté du Query Builder).

Salut,
je ne sais pas si c'est une faute de frappe ou si tu as résolu le problème, mais il me semble que la méthode links() s'applique à websites (au pluriel dans ton cas) et non à website.

{{ $websites->links() }}

essayes:

$websites = Website::all()->sortByDesc('nb_vote')->paginate(10);

@Amilti, je veux pas dire de bêtise, mais paginate() ne s'utilise pas avec get() ou all().
Ça serait plus cela:

$websites = Website::sortByDesc('nb_vote')->paginate(10);

En notant qu'effectivement paginate() se situe après sortByDesc().

luzzbe
Auteur

Merci à vous deux pour votre aide.
J'ai essayé vos deux propositions:

$websites = Website::all()->sortByDesc('nb_vote')->paginate(10);

Ne fonctionne pas, apparemment paginate ne peut pas être appelé après un sortBy.
Method paginate does not exist

$websites = Website::sortByDesc('nb_vote')->paginate(10);

Ne fonctionne pas non plus, sortByDesc ne peut pas être appelé directement sur Website.
Call to undefined method App\Website::sortByDesc()

J'ai l'impression que je vais devoir me servir du QueryBuilder.
Encore merci pour votre aide.

luzzbe
Auteur

@Amilti cette solution me semble très intéressante, je teste dès que j'en ai l'occasion. Merci ;)

Edit: J'ai finalement gardé la solution d'@Amilti. Un énorme merci pour votre aide :).