有没有一种方法可以从构建器获取所有查询,特别是查询以获取急切加载的信息

时间:2019-04-12 15:36:16

标签: sql laravel builder

使用Laravel 5.8.11我有一个多态关系,一个客户可以有很多地址,在这种情况下,其他东西也可以有地址,所以它是多态的。 (称为地址)

我还与客户当前地址保持多态的“具有一个”关系。 (称为地址)

当我尝试运行此查询时:

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

我得到一些奇怪的结果。我得到了所有客户,但只有最后一个客户有地址。

检查种子数据时,所有其他地址都存在,并且如果我通过发送不同的搜索条件来更改结果,则最后一个人将始终返回正确的地址,而其他人将始终为空。

这不是UI问题,因为我只是将结果转储到单元测试中

这是客户端对象上的关系的代码。

   /**
     * 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(),但是有一些帮助程序可以显示backtrace日志中的调用函数没有影响。

我在原始代码块上按如下方式使用它

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%"
    ]
]

但是,我只能从构建器中得到第一个查询。

是否可以获取所有查询?

任何建议都值得赞赏。


更新:

每个@ 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 :(得分:0)

不幸的是,->toSql()没有显示完整的查询,但是有一种方法可以打开查询日志记录并显示上一次查询运行,包括子查询和绑定,并且使用了{{1} }函数:

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();
相关问题