Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Jak zoptymalizować wyświetlanie kategorii w Laravel 7?
Forum PHP.pl > Forum > Przedszkole
trifek
Witam,
Robie projekt w Laravel 7 oraz z wykorzystaniem: https://packagist.org/packages/kalnoy/nestedset.
Mam skrypt który wyświetla mi dane dla jstree https://www.jstree.com

Mam następujący kod kategorii:


  1. Schema::create('categories', function (Blueprint $table) {
  2. $table->bigIncrements('id');
  3. $table->string('category_name', 155);
  4. $table->string('description', 155)->nullable();
  5. $table->string('keywords', 155)->nullable();
  6. $table->longText('content')->nullable();
  7. $table->char('enable', 1)->default(0);
  8. $table->string('photo', 155)->nullable();
  9. $table->bigInteger('order')->default(0);
  10. $table->string('slug', 160)->nullable();
  11. NestedSet::columns($table);
  12. $table->engine = "InnoDB";
  13. $table->charset = 'utf8mb4';
  14. $table->collation = 'utf8mb4_unicode_ci';
  15. });
  16.  
  17.  
  18.  
  19. use App\Traits\ScopeActiveTrait;
  20. use Illuminate\Database\Eloquent\Model;
  21. use Kalnoy\Nestedset\NodeTrait;
  22. use Spatie\Sluggable\HasSlug;
  23. use Spatie\Sluggable\SlugOptions;
  24.  
  25. class Category extends Model
  26. {
  27. use ScopeActiveTrait;
  28. use NodeTrait;
  29. use HasSlug;
  30.  
  31. /**
  32.   * Get the options for generating the slug.
  33.   */
  34. public function getSlugOptions() : SlugOptions
  35. {
  36. return SlugOptions::create()
  37. ->generateSlugsFrom('category_name')
  38. ->slugsShouldBeNoLongerThan(160)
  39. ->saveSlugsTo('slug');
  40. }
  41.  
  42. protected $guarded = ['id'];
  43. protected $fillable = ['category_name', 'description', 'keywords', 'content', 'enable', 'photo', 'order', 'slug', '_lft', '_rgt', 'parent_id'];
  44. public $timestamps = false;
  45.  
  46. }


Kategorii mam ok 170000 rekordów.



Generuje kod dla mojego jstree za pomocą:

  1. public function categoryTree(Category $category, SelectedProductCategory $selectedProductCategory, Request $request)
  2. {
  3. $tree = Cache::remember('categories', 31536000, function () use ($category) {
  4. return $category->active()->get();
  5. });
  6.  
  7. $nodes = $this->generateJsTree($tree->toTree(), ($request->exists('id')) ? $selectedProductCategory->where('product_id', $request->input('id'))->orderBy('id', 'ASC')->get() : null);
  8. return $nodes;
  9. }
  10.  
  11. private function generateJsTree($nodes, $selectedCategories): array
  12. {
  13. $categoryArray = array();
  14. $traverse = function ($categories, $prefix = '-') use (&$traverse, &$categoryArray, $selectedCategories) {
  15. foreach ($categories as $category) {
  16. $selected = false;
  17. if (!is_null($selectedCategories)) {
  18. $selected = $selectedCategories->contains('category_id', $category->id) ? true : false;
  19. }
  20.  
  21. $categoryArray[] = ['id' => $category->id, 'text' => $category->category_name, 'parent' => $category->parent_id questionmark.gif '#', 'state' => ['opened' => false, 'selected' => $selected]];
  22. $traverse($category->children, $prefix . '-');
  23. }
  24. };
  25. $traverse($nodes);
  26. return $categoryArray;
  27. }


(zakładam aktualizację cache raz na rok)



SelectedProductCategory = zaznaczone kategorie


  1. class SelectedProductCategory extends Model
  2. {
  3. protected $fillable = ['product_id', 'category_id'];
  4. protected $guarded = ['id'];
  5. }
  6.  
  7. Schema::create('selected_product_categories', function (Blueprint $table) {
  8. $table->id();
  9. $table->bigInteger('product_id')->unsigned()->default(0);
  10. $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
  11. $table->bigInteger('category_id')->unsigned()->default(0);
  12. $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
  13. $table->timestamps();
  14. });
  15.  




Problem w tym że skrypt generuje się 2 minuty, zarówno na serwerze jak i na lokalnym komputerze sad.gif Plik z cache zajmuje ok 300MB. Co dziwne zarówno jak mam plik z cache, jak i bez niego - skrypt zawsze długo się generuje.

W jaki sposób można to zoptymalizować?
Pyton_000
Generowanie na raz takiej porcji danych to zły pomysł. Użyj Ajax, załaduj kategorie root a potem doczuytuj sobie dynamicznie kolejne poziomy
SmokAnalog
jsTree nawet wspiera Ajax, więc nie musisz zbyt dużo kombinować. Masz bardzo dużo tych kategorii. Tak jak Pyton napisał, pozostaje Ci wczytywać je porcjami. przy odpowiednio zindeksowanej bazie, a zakładam, że ta paczka do Laravela odpowiednio definiuje indeksy dla kolumn, wyszukiwanie danych po ID rodzica będzie błyskawiczne.

Jeśli chcesz się bawić w optymalizację, to możesz np. rozważyć doczytywanie wszystkich kategorii potomnych danego poziomu już w momencie rozwijania dowolnej kategorii z poziomu wyżej, czyli np. jak Twoje drzewko wygląda tak:

Kod
- Jedzenie
--Owoce
---Jabłka
----Zielone
----Czerwone
---Banany
---Owoce leśne
--Warzywa
itd.


W momencie, załadowania strony mógłbyś już mieć wczytane wszystkie kategorie drugiego poziomu, czyli Owoce i Warzywa. Gdy ktoś kliknie Jedzenie, mógłbyś wczytać kategorie trzeciego poziomu, czyli Jabłka, Banany i Owoce Leśne. Gdy ktoś wybierze Owoce, wczytujesz już Zielone i Czerwone dla jabłek itd. Innymi słowy, wyprzedzasz zawsze o jeden poziom. W ten sposób w większości przypadków osiągniesz płynność interfejsu na poziomie aplikacji desktopowej, bo klikanie w poszczególne kategorie zajmie pewnie co najmniej sekundę. Taki podsuwam pomysł, choć i bez tego będzie przyzwoicie.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.