web-dev-qa-db-fra.com

Laravel constructeur de requêtes - réutiliser la requête avec l'instruction where modifiée

Mon application crée et exécute dynamiquement des requêtes complexes pour générer des rapports. Dans certains cas, j'ai besoin d'obtenir plusieurs plages de dates quelque peu arbitraires, avec tous les autres paramètres identiques.

Donc, mon code construit la requête avec un tas de jointures, où, trie, limite etc., puis exécute la requête. Ce que je veux ensuite faire, c'est sauter dans l'objet Builder et changer les clauses where qui définissent la plage de dates à interroger.

Jusqu'à présent, j'ai fait en sorte que la plage de dates soit configurée avant tout autre endroit, puis j'ai essayé de modifier manuellement la valeur dans l'attribut approprié du tableau wherees. Comme ça;

$this->data_qry->wheres[0]['value'] = $new_from_date;
$this->data_qry->wheres[1]['value'] = $new_to_date;

Puis je le fais (l'ayant déjà fait une fois déjà)

$this->data_qry->get();

Ne fonctionne pas cependant. La requête s'exécute uniquement avec la plage de dates d'origine. Même si ma voie fonctionnait, je ne l'aimerais toujours pas, car elle semble être traversée par une dépendance précaire (une sorte de couplage?). C'est à dire; si la date où les lieux ne sont pas définis en premier, tout s'effondre.

I pourrait reconstituer toute la requête à partir de zéro, juste avec une plage de dates différente, mais cela semble ott car tout le reste de la requête doit être le même que la fois précédente.

Toutes les idées sur la façon d'y parvenir de la manière la plus correcte/la plus nette sont les bienvenues.

Merci,

Geoff

28
Geoff Clayton

Vous pouvez utiliser clone pour dupliquer la requête, puis l'exécuter avec différentes instructions where. Commencez par créer la requête sans les contraintes from-to, puis faites quelque chose comme ceci:

$query1 = $this->data_qry;
$query2 = clone $query1;

$result1 = $query1->where('from', $from1)->where('to', $to1)->get();
$result2 = $query2->where('from', $from2)->where('to', $to2)->get();
54
lukasgeiter

La suggestion de @lukasgeiter utilisant clone est certainement la voie à suivre; la raison en est qu'un objet Eloquent\Builder contient une référence interne à un Query\Builder qui doit être dupliqué.

Pour garder le flux de votre application et revenir à un style plus fonctionnel, vous pouvez utiliser l'assistant with() de Laravel, qui retourne simplement l'objet passé:

$result1 = with(clone $this->data_qry)->where('from', $from1)->where('to', $to1)->get();
$result2 = with(clone $this->data_qry)->where('from', $from2)->where('to', $to2)->get();
6
Mark Boots