Je ne comprends vraiment pas, aidez-moi à comprendre.

J'écris une application qui calcule entre autres une "note" d'équipe NFL (une marque est Win / Lose / Tie, désolé je ne connais pas le mot en anglais pour cela), donc j'ai un attribut "Marca" dans le modèle Team, ressemble à ceci:

public function getMarcaAttribute() {
    ...
}

Les requêtes sont très faciles, d'abord j'obtiens le nombre de matchs où l'équipe joue en local et je calcule les victoires, les perdants et les égalités, par exemple, celui-ci est pour les victoires:

$gan += Juego::where('local', $this->id)
                  ->where('score_local', '>', 'score_visitante')
                  ->get()->count();

Ensuite, je fais la même chose avec les jeux en tant que visiteur, mais en inversant les signes de comparaison, bien sûr.

Maintenant, jetons un coup d'œil au jeu Seattle (38) à Atlanta (25), si je le fais dans la base de données

SELECT COUNT(*) FROM juegos WHERE local='atl' AND score_local > score_visitante;

Bien sûr, il renvoie 0.

Dans l'ORM, la requête générée est:

  array (
    'query' => 'select * from `juegos` where `local` = ? and `score_local` > ? and `score_local` is not null',
    'bindings' => 
    array (
      0 => 'atl',
      1 => 'score_visitante',
    ),
    'time' => 0.89,
  ),

Le truc renvoie un 1. J'ai même remplacé le ->count()->get() par un ->get() et fais un foreach sur les résultats:

$gan = Juego::where('local', $this->id)
              ->where('score_local', '>', 'score_visitante')
              ->get();

Log::info('Ganados');
foreach ($gan as $g) {
  Log::info("$g->score_local > $g->score_visitante");
}

La chose renvoie une ligne où il est dit "25> 38"

Je ne comprends vraiment pas ce qui se passe ici. Une idée?

0
luisfer 15 sept. 2020 à 20:06

2 réponses

Meilleure réponse

Vous pouvez y parvenir en utilisant whereRaw:

$gan = Juego::where('local', $this->id)
              ->whereRaw('score_local > score_visitante')
              ->get();

Ou comme suggéré dans les commentaires, whereColumn:

$gan = Juego::where('local', $this->id)
              ->whereColumn('score_local', '>' , 'score_visitante')
              ->get();
3
Pirvu2k 15 sept. 2020 à 17:11

@lagbox l'avait compris dans les commentaires. Le problème est qu'en utilisant des instructions préparées avec des liaisons, le terme score_visitante n'est pas traité comme un nom de colonne plutôt que comme une chaîne.

Il existe plusieurs façons de le résoudre:

  1. Utilisez la méthode Eloquent whereColumn:
$gan += Juego::where('local', $this->id)
                  ->whereColumn('score_local', '>', 'score_visitante')
                  ->count();
  1. Utilisez la méthode Eloquent whereRaw:
$gan += Juego::where('local', $this->id)
                  ->whereRaw('score_local > score_visitante')
                  ->count();
  1. Utilisez DB::raw:
$gan += Juego::where('local', $this->id)
                  ->where('score_local', '>', \DB::raw('score_visitante'))
                  ->count();

Remarque: vous n'avez pas non plus besoin du ->get() avant le ->count(). Vous pouvez demander à la base de données d'effectuer le comptage. Ceci est particulièrement utile lorsque le résultat attendu est un ensemble de données volumineux avec de nombreuses lignes, en renvoyant juste un nombre au lieu de potentiellement des milliers, voire des millions de lignes, vous préservez vos ressources réseau.

1
emiliopedrollo 15 sept. 2020 à 17:45