Weave 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

Baum Laravel Package

akemys/baum

Baum brings the nested set model to Laravel Eloquent, making hierarchical data like categories, menus, and org charts easy to manage. Move nodes, query ancestors and descendants, and rebuild trees with a clean, tested API.

View on GitHub
Deep Wiki
Context7

Getting Started

Version 1.0.1 is a small, non-breaking follow-up to the 1.0 line. The only change — "move with scope opt." — means the move operation now accepts an optional scope argument, letting you move a node/record into a different scope (tenant, tree root, category, locale, etc.) rather than only reordering within its current one.

Minimal steps:

  1. composer update to pull 1.0.1. No migration or config publish is implied by these notes, but re-run php artisan vendor:publish --tag=<package>-config only if the config file is new to you.
  2. Open the class that implements move() and read the method signature first — that is the entire surface area of this release. Confirm where the new optional scope parameter sits in the argument list.
  3. Run your existing test suite before touching anything. The scope argument is opt-in, so pre-1.0.1 calls should behave identically; if they don't, that's your regression signal.
  4. First real use case: take a node you currently move within a tenant/tree, and try passing an explicit target scope to relocate it across scopes in a single call — previously this typically required manual detach/re-attach or a raw update.
// Before: move stayed inside the node's existing scope
$node->move($targetParent);

// After: opt in to a different scope explicitly
$node->move($targetParent, scope: $otherTenant);

Start in the package's tests for move — they double as the clearest documentation of the new argument's accepted types and defaults.

Implementation Patterns

Backwards-compatible default. Treat the scope parameter as "inherit current scope" when omitted. Wrap your existing move calls in a small domain method so the day you need cross-scope moves you change one place, not fifty:

public function relocate(Node $node, ?Node $parent = null, ?Scope $scope = null): void
{
    DB::transaction(fn () => $node->move($parent, $scope));
}

Explicit-scope service methods. Rather than sprinkling the new argument through controllers, expose intent-named actions (moveToTenant(), promoteToRootTree()) that pass the scope explicitly. This keeps the optional argument from becoming an accidental third positional value that callers pass wrong.

Reordering vs. relocating. Separate the two workflows in your code. Sibling reordering should not pass a scope — passing one invites a no-op or an unintended cross-scope hop. Cross-scope relocation should always pass it, even if it equals the current scope, so the intent is explicit and readable in review.

Transactional + locked for concurrent moves. Tree/bound updates touch multiple rows. Always wrap in DB::transaction() and consider lockForUpdate() on the affected subtree rows when moves can be triggered by queued jobs or multiple users simultaneously. Reordering is a classic source of duplicate or gapped bounds under concurrency.

Queue large relocations. Moving a node with many descendants can be expensive. Dispatch a job, and expose a moved-style event or model observer so downstream indexes, search documents, and caches are invalidated after commit — not before.

Testing pattern. Use RefreshDatabase and assert on the observable structure after the move (parent id, scope id, depth/ordering columns) rather than on internal SQL. Include one test per direction: same-scope reorder, cross-scope move, and a move where the scope argument is omitted entirely.

Gotchas and Tips

  • The optional argument is the trap. Because scope is optional, forgetting it silently leaves the node in its old scope. There is no exception to catch — the operation looks successful. Add an assertion in your own wrapper: after a cross-scope move, verify $node->refresh()->scope_id === $targetScope->id.
  • Signature drift. If you have decorators, interfaces, or subclassed repositories that redeclare move(), they now need the extra parameter or they'll be incompatible. Grep for function move( across your app and any first-party extensions.
  • Positional vs. named arguments. Older code calling move($a, $b) may now bind $b to the new scope parameter if it was previously a different second argument. Audit existing call sites with two or more arguments before deploying.
  • Stale in-memory trees. After a move, cached ancestors, descendant collections, and preloaded relations are stale. Call refresh()/load() or unsetRelation(); if you cache rendered trees, key the cache on a tree version bumped after every move.
  • Guard the scope boundary in your own layer. The package will happily move into a scope the user shouldn't touch. Enforce tenancy/authorization in a policy or form request — do not rely on the move call to validate the target scope.
  • Debugging a move that "did nothing": log the resolved scope the method received (dump the argument), confirm the target parent is in that same scope, and check whether a moving/saving observer is short-circuiting. If bounds look corrupted, re-run the package's tree-fix/rebuild command rather than hand-patching columns.
  • Extension point: rather than editing vendor code, override move() in your model/app subclass, call parent::move(...), and layer auditing, event dispatch, or scope-defaulting there. That keeps you on the upgrade path for 1.0.x patches.
  • Pin the version. With a one-line changelog, behavioral details aren't fully documented. Use "^1.0.1" and re-read the source diff between patch releases until the docs catch up.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console