使用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%"
]
]
但是,我只从构建器中获取第一个查询。
有办法获得所有查询吗?
任何建议表示赞赏。
更新:
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
]
]
不幸的是,->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());