El encadenamiento de Laravel Eloquent Query Builder afecta la consulta base original [duplicado]
¿Cómo puedo hacer que esta consulta funcione?
$basic_query = Invoices::between_days(15, 7); // This is a collection of invoices from 15 days ago, to seven days in the future. Notice I am not getting this query, it´s still just a builder instance. If you do dd($basic_query->get()) you get 100 invoices, 60 of them paid, 40 of them outstanding.
$paid_invoices = $basic_query->paid()->get(); // This returns the collection of 60 paid invoices without problems. BUT MODIFIES $basic query, if you dd($basic query->get()) at this point, you only get the 60 paid invoices, not the full 100 invoices collection. ¿?!!!
$outstanding_invoices = $basic_query->paid(false)->get(); // This query will always be empty, even though there are many outstanding invoices. If you dd($basic_query->get()) at this point, you get an empty collection. The 100 invoices are lost.
Entonces, ¿cómo puedo tener una colección básica como punto de partida que no será modificada por operaciones get () subsiguientes?
¡Gracias!
Respuestas
Si tiene un constructor y desea una nueva copia del constructor para poder continuar creando una consulta a partir de él, puede "clonar" el constructor:
$cloned = clone $query;
Ahora $cloned
es su propio objeto y puede crear la consulta como desee sin afectar al $query
constructor original.
Si realmente desea un clone
método en el constructor y no existe, puede aplicar una macro:
Illuminate\Database\Query\Builder::macro('clone', function () {
return clone $this;
});
Puede incluir eso en el boot
método de un proveedor de servicios .
Hay un método de clonación disponible en el constructor (Illuminate \ Database \ Query \ Builder) que se puede utilizar
$basic_query = Invoices::between_days(15, 7); $paid_invoices = $basic_query->clone()->paid()->get(); $outstanding_invoices = $basic_query->clone()->paid(false)->get();
Actualizar
Para las versiones de Laravel por debajo de 8.xa, la macro se puede definir en AppServiceProvider o en un nuevo MacroServiceProvider : método de arranque.
Con MacroServiceProvider, no olvide agregarlo a la matriz de proveedores en config/app.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Query\Builder;
class MacroServiceProvider extends ServiceProvider
{
public function boot()
{
Builder::macro('clone', function() {
return clone $this;
});
}
public function register()
{
//
}
}