filament-adjacency-list
filament-adjacency-list copied to clipboard
[Bug]: Double entries with relationships
What happened?
Hi,
I've 3 entries in my navigation_items database, a hasMany relationship to Navigation Model like this :
Navigation Model Table :
NavigationItem Model Table :
My Navigation Model is like this :
class Navigation extends Model
{
use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
protected $fillable = [
'name' ,
'slug' ,
'position' ,
//'items'
];
public function items(): HasMany
{
return $this->hasMany(NavigationItem::class, 'navigation_id')
->whereNull('parent_id')
->with('childrenAndSelf')
->orderBy('sort');
}
And this is my NavigationItemModel :
class NavigationItem extends Model
{
use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
protected $fillable = ['navigation_id', 'parent_id', 'label', 'sort', 'data'];
public $timestamps = false;
protected $casts = [
'data' => 'array'
];
public function children(): HasMany
{
return $this->hasMany(NavigationItem::class, 'parent_id')
->with('children')
->orderBy('sort');
}
My AdjencyList is like this :
AdjacencyList::make('items')
->label(__('filament-starter::translations.labels.items'))
->visible(fn($record) => $record !== null)
->relationship('items')
//->childrenKey('children')
->maxDepth(config('filament-starter.navigation.settings.max_depth', 6))
->form([ // etc...
When I comment ->whereNull('parent_id') from my Navigation Model, items appears twice, like this :
But when I keep it, only parents appears :
I don't understand if it's a bug or If I do a mistake. I followed the documentation and got this. Any explications ?
Thanks you
How to reproduce the bug
Just create 2 models related with tables :
Navigation
Schema::create('navigations' , function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->string('position');
$table->timestamps();
});
}
// NavigationModel
use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
protected $fillable = [
'name' ,
'slug' ,
'position' ,
//'items'
];
public function items(): HasMany
{
return $this->hasMany(NavigationItem::class, 'navigation_id')
->whereNull('parent_id')
->with('childrenAndSelf')
->orderBy('sort');
}
NavigationItem :
Schema::create('navigation_items' , function (Blueprint $table) {
$table->id();
$table->string('label');
$table->foreignId('navigation_id')->constrained()->references('id')->on('navigations')->cascadeOnDelete();
$table->foreignId('parent_id')->constrained()->references('id')->on('navigation_items')->cascadeOnDelete();
$table->json('data');
$table->string('sort');
});
// NavigationItemModel
use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
protected $fillable = ['navigation_id', 'parent_id', 'label', 'sort', 'data'];
public $timestamps = false;
protected $casts = [
'data' => 'array'
];
public function children(): HasMany
{
return $this->hasMany(NavigationItem::class, 'parent_id')
->with('children')
->orderBy('sort');
}
And NavigationResource :
AdjacencyList::make('items')
->label(__('filament-starter::translations.labels.items'))
->visible(fn($record) => $record !== null)
->relationship('items')
//->childrenKey('children')
->maxDepth(config('filament-starter.navigation.settings.max_depth', 6))
->form([
Forms\Components\TextInput::make('label')
->label('Label')
->required(),
->options(['external_link' => 'External Link']),
Forms\Components\Group::make()
->statePath('data')
->whenTruthy('type')
->live()
->schema([
Forms\Components\TextInput::make('url')
->label(__('filament-starter::translations.labels.url'))
->required(),
Forms\Components\Select::make('target')
->label(__('filament-starter::translations.navigation.select-options.target'))
->options([
'' => __('filament-starter::translations.navigation.select-options.same-tab'),
'_blank' => __('filament-starter::translations.navigation.select-options.new-tab'),
])
->live()
->default(''),
]),
Package Version
2.2.1
PHP Version
8.2.0
Laravel Version
^11
Which operating systems does with happen with?
macOS
Notes
No response
i got the same bug too
I encountered the same issue, and after investigating, it seems the root cause is related to how the nested tree is retrieved.
In staudenmeir/laravel-adjacency-list, the correct way to get a nested tree structure is by using:
Model::tree()->get()->toTree();
However, in this package, the method being used is:
Model::get()->toTree();
This causes the nested tree to return duplicated data, which is unintended.
After looking into the issue further, I found a helpful suggestion from the author in this GitHub issue discussion.
To fix this, you can modify your relationship method like this:
->relationship('items', fn($query, $record) =>
$query->getRelation('children')
->getRelated()::treeOf(fn($queryTree) =>
$queryTree->isRoot()->where('navigation_id', $record->id)
)
)
Additionally, I can confirm that this solution works in v4.0.0-beta1. I recommend considering this version, as it is backward compatible.