indigoram89 / laravel-nested-set
Laravel package for managing hierarchical data using Nested Set pattern with drag-and-drop interface
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/indigoram89/laravel-nested-set
Requires
- php: ^8.4
- illuminate/database: ^12.0
- illuminate/support: ^12.0
- livewire/livewire: ^3.0
Requires (Dev)
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^11.0
README
Пакет для управления иерархическими данными в Laravel с использованием паттерна Nested Set. Включает современный веб-интерфейс на Vue.js 3 с поддержкой drag-and-drop и REST API.
Требования
- PHP 8.4+
- Laravel 12.x
Установка
Через Composer из GitHub
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
Публикация views (опционально)
php artisan vendor:publish --tag=nested-set-views
Публикация assets для веб-интерфейса
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();
Scopes
// Получить корневые узлы Category::query()->roots()->get(); // Получить листья Category::query()->leaves()->get(); // Получить узлы определенной глубины Category::query()->withDepth(2)->get();
Веб-интерфейс на Vue.js
Пакет включает современный веб-интерфейс для управления деревьями с использованием 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
Интерфейс использует следующие 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