filament icon indicating copy to clipboard operation
filament copied to clipboard

CheckboxList: Unable to set constraints for relationship

Open nilskretschmer opened this issue 1 year ago • 1 comments

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

  1. Clone the reproduction repository
  2. See the README for local installation
  3. Login to the Filament Dashboard with [email protected] with password password
  4. Edit one of the seeded Templates
  5. Attach a Group and give the group permissions
  6. Go to another template and attach the same group and also set some permissions
  7. 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

nilskretschmer avatar May 29 '24 14:05 nilskretschmer

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.

github-actions[bot] avatar Mar 20 '25 17:03 github-actions[bot]

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_id instead of just template_id. You can run ddRawSql() on the query to debug it further.

danharrin avatar Jun 21 '25 13:06 danharrin