亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

高效加載或緩存基于許多嵌套關系的視圖

高效加載或緩存基于許多嵌套關系的視圖

PHP
縹緲止盈 2023-08-19 16:42:32
我有無限的類別、子類別、子子類別等等。結構:main--main1-----main2 ( child of main1 )-----main3 ( child of main1 )--main4test我的代碼:在Category.php modelpublic function categories(){    return $this->hasMany(Category::class);}public function childrenCategories(){    return $this->hasMany(Category::class);}在index.blade.php:<select>    @foreach ($categories as $category)        <option value="{{ $category->id }}">{{ $category->category_name }}</option>        @foreach ($cat->childrenCategories as $childCategory)            @include('partials._child_categroy', ['child_category' => $childCategory])        @endforeach    @endforeach</select>在 _child_categroy.blade.php 中<option value="{{ $child_category->id }}">--- {{ $child_category->category_name }}</option>@if ($child_category->categories)    @foreach ($child_category->categories as $childCategory)        @include('partials._child_categroy', ['child_category' => $childCategory])    @endforeach@endif到目前為止一切都很好,但是當我打開調試器時,每個類別級別都有三個查詢,存在循環!這是我的問題,如果我的鏈變得越來越大,那么 foreach 將會增加,這對性能不利!請問有什么建議嗎?
查看完整描述

1 回答

?
MM們

TA貢獻1886條經驗 獲得超2個贊

這個問題及其潛在的問題引起了我的興趣,所以我想了解更多關于整個問題的信息。我自己創建了一個測試場景。


優化

首先對刀片模板的代碼進行一些優化:


// index.blade.php

<select>

? ? @include('categories.options', ['categories' => $categories, 'level' => 0])

</select>


// options.blade.php

@foreach ($categories as $category)

? ? <option value="{{ $category->id }}">{{ str_repeat("--", $level) }} {{ $category->name }}</option>

? ? @include('categories.options', ['categories' => $category->categories, 'level' => $level+1])

@endforeach

然后,我生成了一個包含大約 5000 個嵌套類別、8 層深度的數據庫,以測試加載時間。我的假設是,如果您向類別模型添加急切加載,則可以優化加載時間:


// Category.php


// this eager loads ALL nested relations using levels + 1 queries

protected $with = ['categories'];

// this is not needed and doesn't make any difference

protected $with = ['categories.categories'];

結果如下:


? ? ? ? ? ? ? ? ? ? ? ?Time? Queries? Memory

--------------------------------------------------

? No eager loading? ?12,81 s? ? ?5101? ?112MB

with eager loading? ? 1,49 s? ? ? ? 9? ? 31MB

?2 x eager loading? ? 1,54 s? ? ? ? 9? ? 31MB


Caching? ? ? ? ? ? ? ?0,08 s? ? ? ? 0? ? ?4MB


(stats recorded mainly with debugbar)

正如您所看到的,急切加載絕對是有意義的。在模型中放入一個單一的關系也足夠了$with = ['categories'],laravel 將立即加載所有嵌套的關系 - 整潔!


緩存

因此,為了讓網站盡可能快地加載(我能想到的),唯一真正的解決方案是緩存。


// create new job in console

php artisan make:job RenderCategoryView


// RenderCategoryView.php

public function handle() {

? ? // get all top level categories

? ? $categories = \App\Category::where('category_id', null)->get();

? ? $html = \View::make('categories.options', ['categories' => $categories, 'level' => 0])->render();

? ? file_put_contents(resource_path('views/categories/options_cache.blade.php'), $html);

? ? return true;

}

@include現在您可以像這樣替換刀片模板:


// index.blade.php

@include('categories.options_cache')

要測試 options_cache 文件的生成,您可以執行以下操作:


php artisan tinker

\App\Jobs\RenderCategoryView::dispatchNow();

我還在返回索引視圖之前刪除了現在不必要的數據庫查詢,新的加載時間為83 ms。這并不奇怪,因為現在所有內容都被緩存了。


要在創建、編輯或刪除類別后自動生成新的視圖緩存,您應該將其包含在相應的控制器中:


\App\Jobs\RenderCategoryView::dispatch();


查看完整回答
反對 回復 2023-08-19
  • 1 回答
  • 0 關注
  • 128 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號