Пакет для управления иерархическими данными в Laravel с использованием паттерна Nested Set. Включает современный веб-интерфейс на Vue.js 3 с поддержкой drag-and-drop и REST API.
- PHP 8.4+
- Laravel 12.x
composer require indigoram89/laravel-nested-set
php artisan vendor:publish --tag=nested-set-config
php artisan vendor:publish --tag=nested-set-migrations
php artisan migrate
php artisan vendor:publish --tag=nested-set-views
php artisan vendor:publish --tag=nested-set-assets
Создайте модель, наследующую NestedSetModel
:
<?php
namespace App\Models;
use Indigoram89\NestedSet\Models\NestedSetModel;
class Category extends NestedSetModel
{
protected $table = 'categories';
protected $fillable = ['name', 'slug'];
}
Или используйте trait в существующей модели:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Indigoram89\NestedSet\Traits\NestedSetTrait;
class Category extends Model
{
use NestedSetTrait;
protected $fillable = ['name', 'slug'];
}
Создайте миграцию для вашей таблицы:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('parent_id')->nullable()->index();
$table->integer('lft')->default(0)->index();
$table->integer('rgt')->default(0)->index();
$table->unsignedInteger('depth')->default(0);
$table->string('name');
$table->string('slug')->nullable()->index();
$table->timestamps();
$table->index(['lft', 'rgt']);
$table->index(['parent_id', 'lft']);
});
$root = Category::create(['name' => 'Root Category']);
$root->makeRoot();
$child = Category::create(['name' => 'Child Category']);
$child->makeChildOf($parent);
// Переместить слева от узла
$node->moveToLeftOf($target);
// Переместить справа от узла
$node->moveToRightOf($target);
// Сделать дочерним узлом
$node->makeChildOf($parent);
// Получить всех потомков
$descendants = $node->getDescendants();
// Получить всех предков
$ancestors = $node->getAncestors();
// Получить прямых потомков
$children = $node->getChildren();
// Получить родителя
$parent = $node->getParent();
// Получить соседние узлы
$siblings = $node->getSiblings();
// Получить путь до узла
$path = $node->getPath();
// Получить все дерево
$tree = Category::query()->getTree();
// Является ли узел корневым
$node->isRoot();
// Является ли узел листом (без потомков)
$node->isLeaf();
// Проверка целостности дерева
$node->isValidNestedSet();
// Удалить узел с потомками
$node->deleteSubtree();
// Получить корневые узлы
Category::query()->roots()->get();
// Получить листья
Category::query()->leaves()->get();
// Получить узлы определенной глубины
Category::query()->withDepth(2)->get();
Пакет включает современный веб-интерфейс для управления деревьями с использованием Vue.js 3, Tailwind CSS и REST API.
- 🎯 Выбор модели для управления
- 🌳 Визуализация дерева с анимациями
- 🔍 Поиск по дереву
- ➕ Создание новых узлов
- ✏️ Редактирование существующих узлов
- 🗑️ Удаление узлов с подтверждением
- 🔄 Drag & Drop для перемещения узлов
- 📱 Адаптивный дизайн
- Опубликуйте конфигурацию и assets:
# Опубликовать всё
php artisan vendor:publish --provider="Indigoram89\NestedSet\NestedSetServiceProvider"
# Или по отдельности:
php artisan vendor:publish --tag=nested-set-config
php artisan vendor:publish --tag=nested-set-assets
- Настройте модели в файле
config/nested-set.php
:
'models' => [
[
'name' => 'category',
'class' => App\Models\Category::class,
'label' => 'Категории',
'description' => 'Управление категориями товаров',
],
[
'name' => 'menu',
'class' => App\Models\MenuItem::class,
'label' => 'Меню',
'description' => 'Управление пунктами меню',
],
],
- Откройте в браузере:
http://your-app.test/nested-set
Интерфейс использует следующие API endpoints:
GET /api/nested-set/models
- получить список моделейGET /api/nested-set/{model}/tree
- получить деревоPOST /api/nested-set/{model}/nodes
- создать узелPUT /api/nested-set/{model}/nodes/{id}
- обновить узелDELETE /api/nested-set/{model}/nodes/{id}
- удалить узелPOST /api/nested-set/{model}/reorder
- переупорядочить узлы
- Все запросы защищены CSRF токеном
- Валидация на стороне сервера
- Защита от циклических ссылок при перемещении узлов
Для защиты интерфейса добавьте middleware в маршруты:
Route::prefix('nested-set')
->middleware(['web', 'auth', 'can:manage-trees'])
->group(function () {
Route::get('/', [NestedSetWebController::class, 'index']);
});
Файл конфигурации config/nested-set.php
:
return [
// Названия колонок
'columns' => [
'left' => 'lft',
'right' => 'rgt',
'depth' => 'depth',
'parent_id' => 'parent_id',
],
// Имя таблицы по умолчанию
'table' => 'nested_sets',
// Модели для веб-интерфейса
'models' => [
// Добавьте ваши модели здесь
],
// Настройки производительности
'cache' => [
'enabled' => true,
'ttl' => 3600,
'prefix' => 'nested_set_',
],
];
$categories = Category::query()->roots()->get();
foreach ($categories as $root) {
echo $root->name;
foreach ($root->getChildren() as $child) {
echo '-- ' . $child->name;
foreach ($child->getChildren() as $grandchild) {
echo '---- ' . $grandchild->name;
}
}
}
$category = Category::find($id);
$breadcrumbs = $category->getPath();
foreach ($breadcrumbs as $crumb) {
echo $crumb->name . ' > ';
}
Если структура дерева была повреждена:
$model = new Category();
$model->rebuild();
Запустите тесты:
vendor/bin/phpunit
MIT License