64 lines
2 KiB
PHP
64 lines
2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Resources\CategoryResource;
|
|
use App\Models\Category;
|
|
use App\Models\Product;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
|
|
|
class CategoryController extends Controller
|
|
{
|
|
public function index(): AnonymousResourceCollection
|
|
{
|
|
/** @var Collection<int, Category> $categories */
|
|
$categories = Category::query()
|
|
->where('active', true)
|
|
->select(['id', 'parent_id', 'name', 'slug', 'description', 'sort_order'])
|
|
->orderBy('sort_order')
|
|
->orderBy('name')
|
|
->get();
|
|
|
|
$directProductCounts = Product::query()
|
|
->active()
|
|
->whereNotNull('published_at')
|
|
->selectRaw('category_id, COUNT(*) as aggregate')
|
|
->groupBy('category_id')
|
|
->pluck('aggregate', 'category_id');
|
|
|
|
$childrenByParent = [];
|
|
|
|
foreach ($categories as $category) {
|
|
if ($category->parent_id === null) {
|
|
continue;
|
|
}
|
|
|
|
$childrenByParent[$category->parent_id][] = (int) $category->id;
|
|
}
|
|
|
|
$totalCountsByCategory = [];
|
|
|
|
$countWithDescendants = function (int $categoryId) use (&$countWithDescendants, &$totalCountsByCategory, $childrenByParent, $directProductCounts): int {
|
|
if (isset($totalCountsByCategory[$categoryId])) {
|
|
return $totalCountsByCategory[$categoryId];
|
|
}
|
|
|
|
$total = (int) ($directProductCounts[$categoryId] ?? 0);
|
|
|
|
foreach ($childrenByParent[$categoryId] ?? [] as $childId) {
|
|
$total += $countWithDescendants($childId);
|
|
}
|
|
|
|
$totalCountsByCategory[$categoryId] = $total;
|
|
|
|
return $total;
|
|
};
|
|
|
|
$categories->each(function (Category $category) use ($countWithDescendants): void {
|
|
$category->setAttribute('products_count', $countWithDescendants((int) $category->id));
|
|
});
|
|
|
|
return CategoryResource::collection($categories);
|
|
}
|
|
}
|