filamentphp / filament

A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS.
https://filamentphp.com
MIT License
19.39k stars 2.97k forks source link

Closure inside getStateUsing() called 3 times per row #14852

Open btxtiger opened 1 day ago

btxtiger commented 1 day ago

Package

filament/tables

Package Version

v3.2.124

Laravel Version

v11.33.2

Livewire Version

default

PHP Version

8.3.13

Problem description

When using ->getStateUsing() to fill a column with a custom value, the Closure seems to be called 3 times per row!

image

If this closure contains a custom query, this will lead to triple query execution per row!

Bildschirmfoto 2024-11-20 um 16 16 22

Expected behavior

The Closure should be executed once on page load

Steps to reproduce

Example Column:

Tables\Columns\TextColumn::make('permission_number')
  ->label('Permissions')
  ->badge()
  ->getStateUsing(function (User $user) {
      return $user->permissions()->count();
  }),

Reproduction repository (issue will be closed if this is not valid)

https://github.com/btxtiger/filament-getstateusing-bug-14852

Relevant log output

No response

Donate πŸ’° to fund this issue

Fund with Polar

github-actions[bot] commented 1 day ago

Hey @btxtiger! 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] commented 1 day ago

Thank you for providing reproduction steps! Reopening the issue now.

Cybrarist commented 1 day ago

i think you should use formatStateUsing instead of getStateUsing()

btxtiger commented 1 day ago

@Cybrarist this does not work, since the state of the column should be any query or value (probably also a result of an HTTP request, Cache, other service, ...), and not dependant on a model column.

Cybrarist commented 1 day ago

@btxtiger oh ok, i get what you mean, then why not doing it like the following

$table->modifyQueryUsing(function (Builder $query) {
      $query->withCount('permissions');
})

and then you use 'permissions_count' in your TextColumn.

btxtiger commented 23 hours ago

@Cybrarist yes this would be a workaround for this specific example, but would not solve the actual problem. Let me show you a different example:

Tables\Columns\TextColumn::make('permission_granted')
  ->label('Permissions')
  ->badge()
  ->getStateUsing(function (User $user) {
      return Http::get('https://dummy-auth-provider.com/api/check-permissions', ['uuid' => $user->uuid])
          ->json('permissions_granted') ? 'Granted' : 'Not Granted';
  });

In this case, the closure is still executed 3 times, and thus make 3 https requests * number of rows, for 1 page load