Laravel Eloquent Query Builder 체이닝은 원래 기본 쿼리에 영향을줍니다.

Dec 15 2020

이 쿼리가 작동하도록하려면 어떻게해야합니까?

$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.

그런 다음 후속 get () 작업에 의해 수정되지 않는 시작점으로 기본 컬렉션을 가질 수 있습니다.

감사합니다!

답변

2 lagbox Dec 15 2020 at 01:31

빌더가 있고 빌더의 새 사본이 필요하여 여기에서 쿼리를 계속 빌드 할 수있는 경우 빌더를 "복제"할 수 있습니다.

$cloned = clone $query;

이제 $cloned자체 개체이며 $query원래 작성기 인에 영향을주지 않고 원하는 방식으로 쿼리를 작성할 수 있습니다 .

clone빌더 에서 메소드가 정말로 필요하고 존재하지 않는 경우 매크로를 사용할 수 있습니다.

Illuminate\Database\Query\Builder::macro('clone', function () {
    return clone $this;
});

서비스 공급자의 boot메서드 에이를 던질 수 있습니다 .

2 Donkarnash Dec 15 2020 at 01:35

빌더 (Illuminate \ Database \ Query \ Builder)에서 사용할 수있는 복제 방법이 있습니다.

$basic_query = Invoices::between_days(15, 7); $paid_invoices = $basic_query->clone()->paid()->get(); $outstanding_invoices = $basic_query->clone()->paid(false)->get();

최신 정보

8.xa 이하의 Laravel 버전의 경우 매크로는 AppServiceProvider 또는 새로운 MacroServiceProvider- 부팅 방법 에서 정의 할 수 있습니다 .

MacroServiceProvider 사용-공급자 배열에 추가하는 것을 잊지 마십시오. 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()
    {
        //
    }
}