CheckboxList: Unable to set constraints for relationship
Package
filament/filament
Package Version
3.2.83
Laravel Version
11.9.1
Livewire Version
3.5.0
PHP Version
8.3.7
Problem description
Using the CheckboxList with an intermediate table and a different set of options gives wrong results, because it's not possible to set constraints for the relationship. Also the modifyQueryUsing-method is scoped to the query for the target relationship and not the intermediate table. It seems like it is impossible to set contraints for the intermediate table relationship on the CheckboxList.
The docs also mention a related method modifyOptionsQueryUsing but it doesn't exist:
https://filamentphp.com/docs/3.x/forms/fields/checkbox-list#customizing-the-relationship-query
From the repro repo app/Filament/Resources/TemplateResource/RelationManagers/GroupsRelationManager.php:
private function getPermissionsForm()
{
$checkboxLists = [];
foreach ($this->template->allowedTargets as $target) {
$checkboxLists[] = CheckboxList::make('templatePermissions')
->label($target->name)
->relationship(
name: 'templatePermissions',
titleAttribute: 'name',
modifyQueryUsing: fn (Builder $query) => $query->where('template_id', $this->template->id),
)
->options(function () use ($target) {
$permissions = [];
$templatePermissions = Permission::where('destination_id', $target->id)->whereIn('name', ['download', 'upload'])->get();
foreach ($templatePermissions as $permission) {
$permissions[$permission->id] = $permission->name;
}
return $permissions;
})
->pivotData([
'template_id' => $this->template->id,
]);
}
return $checkboxLists;
}
This form is for a Group-Model that is attached to a Template-Model as an example in the repro repo. The Group-model has a relationship templatePermissions that should be scoped to the current Template-record.
The modifyQueryUsing seems to be ignored completely, because the entries in the intermediate table template_group_permission are always overwritten if the same Group is attached to another Template.
So the problem is that it is impossible to tell Filament that the relationship has some constraints (here the template_id).
Expected behavior
A Group can be attached to a Template and have a constrained relationship to that Template-model through templatePermissions using the intermediate table template_group_permission. Even if the same Group is attached to another Template with the same permissions there should be new entries in the intermediate table instead of overwritten ones.
Steps to reproduce
- Clone the reproduction repository
- See the README for local installation
- Login to the Filament Dashboard with
[email protected]with passwordpassword - Edit one of the seeded Templates
- Attach a Group and give the group permissions
- Go to another template and attach the same group and also set some permissions
- See the intermediate table having overwritten entries instead of new ones
Reproduction repository
https://github.com/nilskretschmer/filament-intermediate-query-issue
Relevant log output
No response
Hey @polar-sh[bot]! We're sorry to hear that you've hit this issue. 💛
However, it looks like you forgot to fill in the reproduction repository URL. Can you edit your original post and then we'll look at your issue?
We need a public GitHub repository which contains a Laravel app with the minimal amount of Filament code to reproduce the problem. Please do not link to your actual project, what we need instead is a minimal reproduction in a fresh project without any unnecessary code. This means it doesn't matter if your real project is private / confidential, since we want a link to a separate, isolated reproduction. That would allow us to download it and review your bug much easier, so it can be fixed quicker. Please make sure to include a database seeder with everything we need to set the app up quickly.
I am a little confused by the example repo, but I have identified two issues that should help you fix this problem if you encounter it again in the future:
- Field names in Filament should be unique. You are creating multiple fields in the same form called
templatePermissions. Consider suffixing this with$target->getKey()in the loop - You can filter through an intermediate table column by prefixing the table name in the query, like
template_group_permission.template_idinstead of justtemplate_id. You can runddRawSql()on the query to debug it further.