Граф вложенных детей Laravel (Категории)

Я использовал вложенные категории на своем сайте Laravel со стилем таблиц mysql со смежным списком. Существует максимум 7 уровней категоризации, (используя Google таксономии категории). Пожалуйста, смотрите изображение ниже для небольшого образца данных, и код ниже для отношений моей модели категории.

Каждая категория имеет от нуля до многих подкатегорий (используя одну и ту же модель категории), а также от нуля до многих страниц под ней. Моя цель заключается в том, чтобы найти способ подсчитать все страницы в категории (включая страницы в ее подкатегориях).

MySql Table Layout Пример

Моя модель категории имеет следующие отношения, которые все работают:

public function pages() {
return $this->hasMany('App\Models\Page');
}

public function children() {
return $this->hasMany('App\Models\Category', 'parent_id' );
}

public function parent() {
return $this->belongsTo('App\Models\Category', 'parent_id' );
}

public function childrenRecursive() {
return $this->children()->orderBy( 'name' )->with('childrenRecursive', 'pages');
}

public function parentRecursive() {
return $this->parent()->with('parentRecursive');
}

0

Решение

Это не то, как я бы сделал это, используя отношения, но хитрый способ был бы:

public function childCount(){
return DB::table('categories')->where('slug', 'LIKE', $this->slug . '%')->count() - 1;
}

Чтобы получить страницы, может быть:

public function pageCount(){
return Page::whereIn('category_id',
DB::table('categories')->select('id')->where('slug', 'LIKE', $this->slug . '%')->get()->pluck('id')
)->count();
}

2 запроса, которые можно было бы оптимизировать, но они бы работали

1

Другие решения

Потому что я с нетерпением жду загрузки всех этих категорий и страниц на первом месте, используя следующую строку кода и мою модель категорий:

$categories = Category::with( 'childrenRecursive' )->whereNull( 'parent_id' )->get();

Я смог использовать рекурсивную формулу, чтобы суммировать количество страниц под каждой категорией, не замедляя страницу:

foreach( $categories as $category ) {
$category->pagesCount = 0;
$category->pagesCount += $category->pages->count();
foreach( $category->childrenRecursive as $child ) {
$category->pagesCount += countChildPages( $child );
}
}

function countChildPages( $category ) {
$category->pagesCount = 0;
$category->pagesCount += $category->pages->count();
foreach( $category->childrenRecursive as $child ) {
$category->pagesCount += countChildPages( $child );
}
return $category->pagesCount;
}

Затем я просто обращался к счетчику ($ category-> pagesCount) всякий раз, когда мне нужно было использовать его на странице.


пример страницы sitemap.html:

foreach( $categories as $category ) {
$category->pagesCount = 0;
$category->pagesCount += $category->pages->count();
foreach( $category->childrenRecursive as $child ) {
$category->pagesCount += countChildPages( $child );
}
}

foreach( $categories as $category ) {
if( $category->pagesCount > 0 ) {
echo '<div class="category">';
echo '<h2><a href="https://example.com/' . $category->slug . '">' . $category->name . ' (' . $category->pagesCount . ')</a></h2>';
foreach( $category->pages as $page ) {
showPage( $page );
}
foreach( $category->childrenRecursive as $child ) {
showSubCategory( $child );
}
echo '</div>';
}
}

function countChildPages( $category ) {
$category->pagesCount = 0;
$category->pagesCount += $category->pages->count();
foreach( $category->childrenRecursive as $child ) {
$category->pagesCount += countChildPages( $child );
}
return $category->pagesCount;
}

function showSubCategory( $category ) {
if( $category->pagesCount > 0 ) {
echo '<div class="category">';
echo '<h2><a href="https://example.com/' . $category->slug . '">' . $category->name . ' (' . $category->pagesCount . ')</a></h2>';
foreach( $category->pages as $page ) {
showPage( $page );
}
foreach( $category->childrenRecursive as $child ) {
showSubCategory( $child );
}
echo '</div>';
}
}

function showPage( $page ) {
echo '<div class="category page">';
echo '<h2><a href="https://example.com/' . $page->slug . '">' . $page->title . '</a></h2>';
echo '</div>';
}
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector