Есть ли способ получить все запросы от застройщика, в частности запрос получения загруженной информации - PullRequest
2 голосов
/ 12 апреля 2019

Использование Laravel 5.8.11 У меня полиморфное отношение ко многим, у клиентов может быть много адресов, в другом случае в этом случае могут быть адреса, поэтому это полиморфно. (вызываемые адреса)

Я также сохраняю полиморфное отношение "имеет один" к текущему адресу клиента (вызываемый адрес)

Когда я пытаюсь выполнить этот запрос:

return Client::with('address')
    ->where('first_name', 'like', '%' . $search . '%')
    ->orWhere('last_name', 'like', '%' . $search . '%')
    ->get();

Я получаю некоторые странные результаты обратно. Я получаю всех клиентов, но адрес есть только у последнего клиента.

При проверке начальных данных присутствуют все остальные адреса, и если я изменю результаты, отправив в других критериях поиска, последний человек всегда будет возвращаться с правильным адресом, в то время как у других всегда будет нулевой.

Это не проблема пользовательского интерфейса, так как я просто вывожу результат в модульном тесте

Вот код для отношений на клиентском объекте.

   /**
     * Get the address records associated with the Model.
     */
    public function addresses() :MorphMany
    {
        return $this->morphMany(Location::class, 'has_location')->latest();
    }

    /**
     * Get the latest address record associated with the Model.
     */
    public function address() :MorphOne
    {
        return $this->morphOne(Location::class, 'has_location')->latest('id')->limit(1);
    }

Когда я пытаюсь выяснить, что я называю из базы данных, я пытаюсь перехватить отправляемый SQL. Я просто использую простую функцию, чтобы перестроить полный SQL для облегчения чтения с помощью этого:

function ddsql($builder, $replace = false)
{
    if (!$replace)
        return ddf([$builder->toSql(), $builder->getBindings()]);
    $sql = $builder->toSql();
    ddf(Str::replaceArray('?', $builder->getBindings(), $sql));
}

ddf () - это в основном dd (), но некоторые помощники показывают, что вызывающая функция из журналов обратной трассировки не имеет никакого отношения.

Я использую его следующим образом в исходном кодовом блоке

ddsql(
    Client::with('address')
        ->where('first_name', 'like', '%' . $search . '%')
        ->orWhere('last_name', 'like', '%' . $search . '%')
);

, который возвращает первый запрос, но не шаг загрузки, который, вероятно, там, где проблема.

Array
[
    "select * from `clients` where `first_name` like ? or `last_name` like ?",
    [
        "%co%",
        "%co%"
    ]
]

Однако я получаю только первый запрос от разработчика.

Есть ли способ получить все запросы?

Любые советы приветствуются.


UPDATE:

Per @ tim-lewis, (спасибо) Я обновил функцию, которую я использовал, чтобы это было некрасиво, но выполняет свою работу.

/** @test */
    public function clients_matching_search_are_returned_with_their_addresses() {
        $client1 = ObjectFactory::clientWithAnAddress(['client'=>['first_name'=>'Test 1']]);
        $client2 = ObjectFactory::clientWithAnAddress(['client'=>['first_name'=>'Test 2']]);
        $client3 = ObjectFactory::clientWithAnAddress(['client'=>['first_name'=>'Test 3']]);


        ddSqlCollection(function(){return Client::with('address')->get();});

}

//WHERE ddSqlCollection is the following

function ddSqlCollection($callback, $replace = false){

    $callback = $callback ?: function () {
        return true;
    };

    DB::flushQueryLog();
    DB::enableQueryLog();
    $callback();
    DB::disableQueryLog();
    ddf(DB::getQueryLog());

}

Я уверен, что есть более красивый способ, и я все еще не уверен, почему данные, которые я получаю, не соответствуют тому, что я считаю, что SQL должен возвращаться, однако я спрошу тех, кто более сфокусирован вопрос.

Вот результат, который ожидался:

"ddSqlCollection(["Closure"])"
"Tests\Feature\Clinet\SearchTest\clients_matching_search_are_returned_with_their_addresses([])"
"-------------------------------------------"
array:2 [
  0 => array:3 [
    "query" => "select * from "clients""
    "bindings" => []
    "time" => 0.06
  ]
  1 => array:3 [
    "query" => "select * from "locations" where "locations"."has_location_id" in (1, 2, 3) and "locations"."has_location_type" = ? order by "id" desc limit 1"
    "bindings" => array:1 [
      0 => "App\Client"
    ]
    "time" => 0.19
  ]
]

1 Ответ

0 голосов
/ 12 апреля 2019

К сожалению, ->toSql() не показывает полный запрос, но есть способ включить ведение журнала запросов и отобразить последний запуск запроса, включая подзапросы и привязки, при этом используется функция enableQueryLog():

\DB::connection()->enableQueryLog();

Затем, после выполнения запроса, вы можете сразу же dd() результат показать ваш запрос.Например:

$user = User::with(["role"])->first();
$lastQuery = collect(\DB::getQueryLog())->last(); // or end(\DB::getQueryLog());

dd($lastQuery);

В моей ситуации это приводит к следующему:

array:3 [▼
  "query" => "select `roles`.*, `role_users`.`user_id` as `pivot_user_id`, `role_users`.`role_id` as `pivot_role_id` from `roles` inner join `role_users` on `roles`.`id` = `role_users`.`role_id` where `role_users`.`user_id` in (?)"
  "bindings" => array:1 [▼
    0 => 1
  ]
  "time" => 0.9
]

Примечание. Использование collect(\DB::getQueryLog())->last(); - это просто быстрый способ вернуть только последний выполненный запрос.Если вы хотите, чтобы все запросы выполнялись в текущем запросе, просто выполните:

dd(\DB::getQueryLog());
...