Installation:
composer require toponepercent/baum
Publish the migration (if needed):
php artisan vendor:publish --provider="TopOnePercent\Baum\BaumServiceProvider" --tag="migrations"
Run migrations:
php artisan migrate
Model Setup:
Use the Baum\NodeTrait in your Eloquent model:
use TopOnePercent\Baum\NodeTrait;
class Category extends Model
{
use NodeTrait;
protected $fillable = ['name', 'slug'];
}
First Use Case: Create a root node:
$root = Category::create(['name' => 'Electronics']);
Add a child node:
$child = $root->children()->create(['name' => 'Phones']);
config/baum.php (for customization)database/migrations/ (for schema adjustments)app/Models/ (your model using NodeTrait)Hierarchy Management:
$parent = Category::find(1);
$child = $parent->appendChild(['name' => 'Laptops']);
$node = Category::find(2);
$node->moveTo($parent, 'last-child'); // or 'first-child', 'after', 'before'
Querying:
$root = Category::roots()->first();
$children = $root->children;
$level2Nodes = Category::whereDepth(2)->get();
Tree Traversal:
$root->descendants; // All descendants
$root->ancestors; // All ancestors
$root->siblings; // Sibling nodes
Bulk Operations:
$nodes = Category::where('parent_id', 1)->orderBy('lft')->get();
$nodes->each->reorder();
toTree() for nested JSON responses:
return Category::roots()->toTree();
spatie/laravel-medialibrary for file uploads in tree nodes.use TopOnePercent\Baum\Rules\Depth;
$rules = ['depth' => ['max', 3]];
Migration Conflicts:
lft/rgt columns, always use Baum’s migrations or schema:baum to avoid corruption.lft/rgt are manually modified.Performance with Large Trees:
select('id', 'name') to limit columns.remember():
$root = Category::roots()->remember(60)->first();
Circular References:
CircularReferenceException.$node->isDescendantOf($target) before moving.Soft Deletes:
SoftDeletes trait + override delete():
public function delete()
{
$this->deleteChildren();
parent::delete();
}
Tree Validation:
php artisan baum:validate
Fixes inconsistencies in lft/rgt values.
Log Tree Structure:
$root->dumpTree(); // Dumps hierarchy to logs
Custom Scopes:
class Category extends Model
{
public function scopeActive($query)
{
return $query->where('is_active', true)->withDescendants();
}
}
Event Hooks:
baum.node.moved or baum.node.created:
Baum::addListener('baum.node.created', function ($node) {
// Post-create logic
});
Custom Paths:
Override getPathAttribute() for unique slug paths:
public function getPathAttribute()
{
return $this->ancestors()->pluck('slug')->implode('/') . '/' . $this->slug;
}
lft for ordering. Override in app/Models/Category.php:
protected $orderBy = ['name' => 'asc'];
config/baum.php:
'cache_depth' => false,
How can I help you explore Laravel packages today?