我有一个简单的数据库,有两个表。orders -主表,关于16_000记录。每个订单都有付款。order_payments表是关于17_000记录的。另外,每个order_tourists表- 33_000行中都可以有零个或更多的旅行者。
订单模型如下所示
namespace App;
class Order extends \Illuminate\Database\Eloquent\Model
{
public function payments()
{
return $this->hasMany('App\OrderPayment');
}
public function tourists()
{
return $this->hasMany('App\OrderTourist');
}
}我有一个简单的任务来显示所有订单的分页列表。此列表中的每一项都应显示某些订单的信息(来自orders表)、所有支付的总和和所有旅行者的姓名。
我想到的第一件事是这样的。
获取支付和旅行者的所有订单,并将这些数据传递给视图。
Route::get('search_offers', static function () {
$orders = \App\Order::query()->with(['payments', 'tourists']);
return view('orders', [
'orders' => $orders->paginate(),
]);
});我的orders.blade.php很简单
<ol>
@foreach($orders as $order)
<li>
{{$order->request_id}}; {{ $order->payments->sum('amount') }}; {{ $order->tourists->implode('fullName', ', ') }}
</li>
@endforeach
</ol>但是,即使是查询的数量也很小--我对模型有很多操作。我添加了一个自定义钩子来跟踪所有雄辩的事件。*在第一种情况下,这类事件的23_000更多。

然后,我试图删除关系的加载,因此,对于每一个订单,Laravel必须运行一个单独的查询,以获得所有订单的付款和旅行者。我只是在我的控制器里这么做了
return view('orders', [
'orders' => \App\Order::query()->paginate(),
]);因此,我得到了更多的查询,但是页面速度有所提高,一些受影响的模型明显减少。

为了跟踪受影响的模型,我在AppServiceProvider::boot方法中添加了一个listner,并在一个调试器面板中输出了AppServiceProvider::$水合模型的值
Event::listen('eloquent.*', static function ($event) {
if (strpos($event, 'eloquent.retrieved') !== false) {
AppServiceProvider::$hydratedModels++;
}
});所以,我的问题是,即使我只显示了15项,怎么可能检索到这么多模型。看起来,Laravel以某种方式将它们全部处理,但只对所需的页面进行了回放。
现在,运行额外的查询来获取一些数据并不是什么大事,但我想知道,也许我做错了什么,也有可能加载关系,但不会导致Laravel检索所有模型。
发布于 2019-08-22 06:29:51
我发现了问题。谢谢,@dparoli,谢谢你的建议。
我的模型有一个主键作为UUID。但是我没有改变Model::$keyType,所以在内部Laravel将它转换成一个整数,查询如下所示。

我得到的不是UUID字符串,而是用于相关记录的整数作为order_id。
因此,我添加了protected $keyType = 'string'; ,一切都按预期开始工作。
PS。不过,我想知道它以前是怎么工作的。
https://stackoverflow.com/questions/57597554
复制相似问题