Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Yii2 Nested Sets Laravel Package

creocoder/yii2-nested-sets

Yii2 Nested Sets Behavior implementing the Modified Preorder Tree Traversal algorithm for hierarchical data. Adds ActiveRecord behavior and query helpers for inserting, moving, and deleting nodes, with optional multi-tree support via a tree attribute.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require creocoder/yii2-nested-sets
    

    (Note: This is a Yii2 package, but Laravel equivalents like artesaos/seotools or spatie/laravel-activitylog can inspire similar workflows in Laravel.)

  2. Model Integration In your Laravel model (e.g., Category), attach the behavior:

    use Creocoder\NestedSets\NestedSetsBehavior;
    
    class Category extends Model
    {
        public function behaviors()
        {
            return [
                'tree' => [
                    'class' => NestedSetsBehavior::class,
                    'depthAttribute' => 'depth',
                ],
            ];
        }
    }
    

    (Laravel alternative: Use Spatie\Tree\Traits\HasTree or Kalnoy\Nestedset\NodeTrait.)

  3. Database Migration Add lft (left value) and rgt (right value) columns to your table:

    Schema::table('categories', function (Blueprint $table) {
        $table->integer('lft')->unsigned();
        $table->integer('rgt')->unsigned();
    });
    
  4. First Use Case Insert a root node:

    $root = Category::create(['name' => 'Root']);
    $root->saveTree(); // Triggers nested set update
    

Implementation Patterns

Common Workflows

  1. Tree Traversal Fetch a subtree (Laravel equivalent using Spatie\Tree):

    $children = Category::where('parent_id', $parent->id)->with('children')->get();
    

    (Nested sets optimize this with lft/rgt range queries.)

  2. Dynamic Sorting Reorder nodes via drag-and-drop (e.g., with SortableJS):

    // After reordering, update positions:
    Category::reorder(); // Hypothetical method (use `Spatie\Tree` or manual `lft`/`rgt` recalculation).
    
  3. Performance-Critical Queries Use lft/rgt for O(1) subtree checks:

    // Find all descendants of a node (Laravel + Nested Sets):
    $descendants = Category::where('lft', '>', $node->lft)
                            ->where('rgt', '<', $node->rgt)
                            ->get();
    
  4. Soft Deletes Handle soft deletes by adjusting lft/rgt gaps (custom logic required).

Integration Tips

  • Eloquent Events: Listen for saved/deleted to auto-update nested sets:
    Category::observe(CategoryObserver::class);
    
    class CategoryObserver {
        public function saved(Category $category) {
            $category->updateTree(); // Hypothetical (use `Spatie\Tree` or manual recalculation).
        }
    }
    
  • API Responses: Serialize trees with recursive JSON:
    $tree = Category::with('children')->where('parent_id', null)->get()->toTree();
    

Gotchas and Tips

Pitfalls

  1. Concurrency Issues

    • Nested set updates require atomic transactions. Use Laravel’s DB::transaction():
      DB::transaction(function () {
          $node->updateTree(); // Hypothetical (or use `Spatie\Tree`).
      });
      
  2. Performance on Large Trees

    • Recalculating lft/rgt for 10,000+ nodes is slow. Batch updates or use a library like Kalnoy/Nestedset.
  3. Circular References

    • Prevent infinite loops in recursive queries by adding depth limits:
      $tree = Category::where('lft', '>', $root->lft)
                      ->where('rgt', '<', $root->rgt)
                      ->where('depth', '<', 20) // Safety limit
                      ->get();
      
  4. Migration Pitfalls

    • Ensure lft/rgt columns are unsigned and indexed:
      $table->integer('lft')->unsigned()->index();
      $table->integer('rgt')->unsigned()->index();
      

Debugging

  • Invalid Trees: Use this query to validate lft/rgt consistency:

    SELECT id, lft, rgt, (rgt - lft + 1) AS width
    FROM categories
    ORDER BY lft;
    

    (All widths should be odd numbers.)

  • PHP Errors: Check for missing depthAttribute or invalid parent_id references.

Extension Points

  1. Custom Sorting Override getTreeQuery() to add custom conditions:

    public function getTreeQuery() {
        return parent::getTreeQuery()->where('is_active', 1);
    }
    
  2. Alternative Storage Store lft/rgt in a different column name by configuring the behavior:

    'tree' => [
        'class' => NestedSetsBehavior::class,
        'leftAttribute' => 'left_val',
        'rightAttribute' => 'right_val',
    ],
    
  3. Laravel-Specific Tips

    • Use Spatie\Tree or Kalnoy/Nestedset for modern Laravel support.
    • For Yii2-to-Laravel porting, replace ActiveRecord with Eloquent and adapt behaviors to observers/traits.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport