on1kel/hyperf-nestedset 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

on1kel/hyperf-nestedset

Composer 安装命令:

composer require on1kel/hyperf-nestedset

包简介

Multi-Treeструктуры для Hyperf (реализация модели вложенных наборов)

README 文档

README

PHP Hyperf Package Hyperf Version License

Пакет Hyperf для реализации многодеревьевых иерархических структур с использованием модели вложенных множеств (Nested Set Model).

Обзор

Пакет поддерживает Multi-Tree структуры (несколько корневых узлов) и позволяет перемещать узлы между деревьями. Работает с различными типами первичных ключей: int, uuid и ulid.

Ключевые преимущества

  • Multi-Tree поддержка: Управление несколькими независимыми деревьями в одной таблице
  • Кросс-дерево операции: Легкое перемещение узлов между различными деревьями
  • Гибкие первичные ключи: Работа с различными типами ключей, включая int, uuid и ulid
  • Оптимизация производительности: Эффективное извлечение иерархических данных с минимальным количеством запросов к БД
  • Поддержка современного PHP: Использование современных возможностей PHP 8.x и строгой типизации
  • Гибкая конфигурация: Широкие возможности настройки имен атрибутов и поведения

Что такое вложенные множества?

Nested Set Model — эффективный способ хранения иерархических данных в реляционных базах данных:

Модель вложенных множеств нумерует узлы в соответствии с обходом дерева, который посещает каждый узел дважды, присваивая номера в порядке посещения при каждом визите. Это оставляет два числа для каждого узла, которые хранятся как атрибуты. Запросы становятся недорогими: принадлежность к иерархии можно проверить сравнением этих чисел. Обновление требует перенумерации и поэтому является дорогим.

Идеальные случаи использования

NSM показывает хорошую производительность когда:

  • Деревья обновляются редко
  • Требуется быстрое извлечение связанных узлов
  • Построение многоуровневых меню или структур категорий

Требования

  • PHP: 8.2|8.3|8.4
  • Hyperf: ^3.1.*

Настоятельно рекомендуется использовать базу данных, поддерживающую транзакции (например, PostgreSQL), для защиты структуры дерева от повреждения.

Установка

composer require on1kel/hyperf-nestedset

Базовое использование

Настройка модели

Чтобы сделать модель узлом дерева, добавьте трейт UseTree:

<?php

declare(strict_types=1);

namespace App\Model;

use Hyperf\Database\Model\Model;
use On1kel\NestedSet\UseTree;

class Category extends Model
{
    use UseTree;

    protected ?string $table = 'categories';

    protected array $fillable = ['name', 'parent_id'];
}

Миграция

Используйте хелпер миграции для создания необходимых колонок:

<?php

use Hyperf\Database\Schema\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Migrations\Migration;
use On1kel\NestedSet\Database\Migrate;
use App\Model\Category;

class CreateCategoriesTable extends Migration
{
    public function up(): void
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            
            // Добавить колонки nested set из модели
            Migrate::columnsFromModel($table, Category::class);
            
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('categories');
    }
}

Создание узлов

Создание корневого узла

// Для модели с одним деревом
$root = new Category(['name' => 'Корень']);
$root->saveAsRoot();

// Или используя makeRoot()
$root = new Category(['name' => 'Корень']);
$root->makeRoot()->save();

Создание дочерних узлов

// Добавить в конец (как последний дочерний)
$child = new Category(['name' => 'Дочерний']);
$child->appendTo($parent)->save();

// Добавить в начало (как первый дочерний)
$child = new Category(['name' => 'Дочерний']);
$child->prependTo($parent)->save();

Создание соседних узлов

// Вставить перед узлом
$sibling = new Category(['name' => 'Сосед']);
$sibling->insertBefore($existingNode)->save();

// Вставить после узла
$sibling = new Category(['name' => 'Сосед']);
$sibling->insertAfter($existingNode)->save();

Перемещение узлов

// Переместить узел к другому родителю
$node->appendTo($newParent)->save();

// Переместить узел перед соседом
$node->insertBefore($sibling)->save();

// Переместить узел после соседа
$node->insertAfter($sibling)->save();

// Переместить вверх среди соседей
$node->up();

// Переместить вниз среди соседей
$node->down();

Получение узлов

Получить корень

$root = Category::root()->first();
// или
$root = $node->getRoot();

Получить родителя

$parent = $node->parent;

Получить детей

$children = $node->children;

Получить предков

$ancestors = $node->ancestors;
// или через query builder
$ancestors = $node->parents();

Получить потомков

$descendants = $node->descendants;
// или через query builder
$descendants = $node->newQuery()->descendantsQuery()->get();

Получить соседей

$siblings = $node->siblings()->get();
$siblingsAndSelf = $node->siblingsAndSelf()->get();

Получить листья (узлы без детей)

$leaves = $node->leaves()->get();

Построение дерева

$tree = Category::defaultOrder()->get()->toTree();

Проверка состояния узла

$node->isRoot();    // Это корневой узел?
$node->isLeaf();    // Это лист (без детей)?
$node->isChildOf($otherNode);  // Это дочерний узел другого?

Удаление узлов

// Удалить узел (дети будут перемещены к родителю)
$node->delete();

// Удалить узел со всеми потомками
$node->deleteWithChildren();

Поддержка Multi-Tree

Для включения поддержки нескольких деревьев, переопределите метод buildTree:

<?php

namespace App\Model;

use Hyperf\Database\Model\Model;
use On1kel\NestedSet\UseTree;
use On1kel\NestedSet\Config\Builder;

class Category extends Model
{
    use UseTree;

    protected static function buildTree(): Builder
    {
        return Builder::defaultMulti();
    }
}

Затем можно работать с несколькими деревьями:

// Создать корни для разных деревьев
$tree1Root = new Category(['name' => 'Корень дерева 1']);
$tree1Root->setTree(1)->saveAsRoot();

$tree2Root = new Category(['name' => 'Корень дерева 2']);
$tree2Root->setTree(2)->saveAsRoot();

// Запрос по дереву
$tree1Nodes = Category::byTree(1)->get();

Query Scopes

// Получить только корневые узлы
Category::root()->get();

// Получить узлы по дереву (только multi-tree)
Category::byTree($treeId)->get();

// Получить узлы по уровню
Category::byLevel(2)->get();

// Получить узлы до определенного уровня
Category::toLevel(3)->get();

// Сортировка по умолчанию (по левому атрибуту)
Category::defaultOrder()->get();

Лицензия

MIT License. См. LICENSE.md для деталей.

Благодарности

Этот пакет является портом efureev/laravel-trees для Hyperf.

on1kel/hyperf-nestedset 适用场景与选型建议

on1kel/hyperf-nestedset 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 37 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 12 月 26 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「tree」 「nestedset」 「hierarchy」 「nested-set」 「hyperf」 「multi-tree」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 on1kel/hyperf-nestedset 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 on1kel/hyperf-nestedset 我们能提供哪些服务?
定制开发 / 二次开发

基于 on1kel/hyperf-nestedset 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 37
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 21
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-26