Существует как минимум два решения.
Решение 1 (Pure Laravel):
Добавьте эти два метода в модель Category
:
public function descendants()
{
$collection = new \Illuminate\Support\Collection();
foreach ($this->children as $child) {
$collection->add($child);
$collection = $collection->merge($child->descendants());
}
return $collection;
}
public function getRouteKeyName()
{
return 'slug';
}
И используйте его в вашем ProductController
контроллере следующим образом:
class ProductController extends Controller
{
public function index(Request $request, Category $category)
{
$categories = $category->descendants()->add($category)->pluck('id');
$products = DB::table('category_product AS cp')
->join('products', 'cp.product_id', '=', 'products.id')
->select('products.*')
->whereIn('cp.category_id', $categories)
->get();
return view('products', compact('category', 'products'));
}
}
Затем вы можете вывести их в свой файл вида:
@forelse($products as $product)
<div class="product">
<img border="0" src="{{ Voyager::image($product->image) }}" alt="{{ $product->name }}">
<div class="product-name">{{ $product->name }}</div>
<div class="product-price">${{ $product->price }}</div>
</div>
@empty
<div class="product">
There are no products in this category.
</div>
@endforelse
Решение 2 (с использованием пакета ):
Прежде всего установите пакет:
composer require kalnoy/nestedset
Замените parent_id
столбец на $table->nestedSet();
in Ваша таблица categories
и связанный файл миграции:
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('slug')->unique();
$table->nestedSet();
$table->timestamps();
});
Затем обновите модель Category
следующим образом:
use Illuminate\Database\Eloquent\Model;
use Kalnoy\Nestedset\NodeTrait;
class Category extends Model
{
use NodeTrait;
protected $fillable = [
'name',
'slug',
];
public function products()
{
return $this->belongsToMany('App\Product');
}
public function parent()
{
return $this->belongsTo(self::class, 'parent_id');
}
public function children()
{
return $this->hasMany(self::class, 'parent_id');
}
public function getRouteKeyName()
{
return 'slug';
}
}
Теперь вы можете использовать ее в вашем контроллере:
class ProductController extends Controller
{
public function index(Request $request, Category $category)
{
$categories = Category::descendantsAndSelf($category->id)->pluck('id');
$products = DB::table('category_product AS cp')
->join('products', 'cp.product_id', '=', 'products.id')
->select('products.*')
->whereIn('cp.category_id', $categories)
->get();
return view('products', compact('category', 'products'));
}
}
Вы можете выводить, как показано в Решение 1 .
Обратите внимание, что я предположил, что вы используете {category}
ключ в вашем определение маршрута. (См. Привязка модели маршрута ) Например:
Route::get('/products/category/{category}', 'ProductController@index');
Сначала прочитайте документацию , чтобы создать, обновить и удалить элемент во вложенном наборе (категориях).