- Lunar version: 1.3.0
- Laravel Version: 12.55.1
- PHP Version: 8.3.29
- Database Driver & Version: MySQL 8.4
Expected Behaviour:
When deleting a child collection from a nested collection tree, the nested set values (_lft and _rgt) should be recalculated correctly.
For example, if a collection has multiple child collections and one of the middle children is deleted, the remaining right-side siblings should keep valid and unique _lft / _rgt values according to the nested set structure.
This should also work correctly when the Lunar Collection model is replaced with a custom application model as described in the documentation.
Actual Behaviour:
If the Collection model is replaced with a custom model extending \Lunar\Models\Collection, deleting a child collection that has at least two right-side siblings corrupts the nested set values.
After the deletion, the _lft and _rgt values of the right-side siblings become invalid / duplicated, as shown in the screenshots.
Example setup:
- Create several root collections.
- Create multiple child collections under collection
2.
- Delete one of the middle child collections (for example the second child), while it has at least two siblings to its right.
Result:
- The remaining right-side siblings end up with broken
_lft / _rgt values.
This issue only appears when the Collection model is overridden/replaced via ModelManifest.
Steps To Reproduce:
- Replace the Lunar
Collection model with a custom application model:
namespace App\Models;
class Collection extends \Lunar\Models\Collection
{
public function someCustomMethod()
{
return 'Hello!';
}
}
- Register the replacement in a service provider:
public function boot()
{
\Lunar\Facades\ModelManifest::replace(
\Lunar\Models\Contracts\Collection::class,
\App\Models\Collection::class,
);
}
- Create a few root collections.
- Create multiple child collections under one parent collection (for example under collection 2).
Example:
- Delete one of the middle child collections, ensuring it has at least two siblings to its right.
- Check the _lft and _rgt values in the database.
Additional Notes:
I investigated this a bit and it seems related to the kalnoy/nestedset package.
In NodeTrait::bootNodeTrait, the relevant logic appears to run twice for the same model during deletion. On the first execution, the database values are still correct. On the second execution, the _lft / _rgt values become corrupted.
I confirmed this by adding debug output:
If I use dump(), I can see the same model being processed twice.
If I use dd() on the first execution, the process stops and the database values remain correct.
This suggests the second execution is what breaks the tree.
I traced this further and it seems the issue may be caused by Lunar's HasModelExtending trait, where fireModelEvent is overridden. My assumption is that when the Collection model is extended/replaced, the deleted event may be dispatched twice, which then causes the nested set deletion logic to run twice as well.
I am opening this bug report because I managed to narrow the issue down to this point, but I am not sure what the correct fix should be. Hopefully this investigation helps.
Expected Behaviour:
When deleting a child collection from a nested collection tree, the nested set values (
_lftand_rgt) should be recalculated correctly.For example, if a collection has multiple child collections and one of the middle children is deleted, the remaining right-side siblings should keep valid and unique
_lft/_rgtvalues according to the nested set structure.This should also work correctly when the Lunar
Collectionmodel is replaced with a custom application model as described in the documentation.Actual Behaviour:
If the
Collectionmodel is replaced with a custom model extending\Lunar\Models\Collection, deleting a child collection that has at least two right-side siblings corrupts the nested set values.After the deletion, the
_lftand_rgtvalues of the right-side siblings become invalid / duplicated, as shown in the screenshots.Example setup:
2.Result:
_lft/_rgtvalues.This issue only appears when the
Collectionmodel is overridden/replaced viaModelManifest.Steps To Reproduce:
Collectionmodel with a custom application model:Example:
Additional Notes:
I investigated this a bit and it seems related to the kalnoy/nestedset package.
In NodeTrait::bootNodeTrait, the relevant logic appears to run twice for the same model during deletion. On the first execution, the database values are still correct. On the second execution, the _lft / _rgt values become corrupted.
I confirmed this by adding debug output:
If I use dump(), I can see the same model being processed twice.
If I use dd() on the first execution, the process stops and the database values remain correct.
This suggests the second execution is what breaks the tree.
I traced this further and it seems the issue may be caused by Lunar's HasModelExtending trait, where fireModelEvent is overridden. My assumption is that when the Collection model is extended/replaced, the deleted event may be dispatched twice, which then causes the nested set deletion logic to run twice as well.
I am opening this bug report because I managed to narrow the issue down to this point, but I am not sure what the correct fix should be. Hopefully this investigation helps.