Tenancy and BadgeCount - seems to cause an N+1 problem of sorts

First of all... I love Filament! I have a v3 installation running with Tenancy: user client client_user Very simple implementation. For each Resource, I would like to display the "badge count" in the sidebar navigation menu. Take a look at: public static function getNavigationBadge(): ?string { return static::getModel()::count(); } public static function getNavigationBadgeColor(): ?string { return static::getModel()::count() > 10 ? 'info' : 'gray'; } Straight from the docs. The problem is that I get 4 queries for "each" Tenant, of which I have 8 for a total of 32 duplicated queries. Has anyone ran into this kind of problem before? It seems that Filament::getTenant() works as it should, but is looping over every Tenant even though I'm only viewing data for one Tenant. Any advice is greatly appreciated!
14 Replies
wyChoong
wyChoong15mo ago
You running count for 2 times so it obviously going to get duplicated queries
mar5hall
mar5hall15mo ago
It’s from official documentation
wyChoong
wyChoong15mo ago
So? But do you understand what the code you copied do?
mar5hall
mar5hall15mo ago
I definitely understand this code. It's obvious that count is called multiple times. But I don’t think that even in this case it will lead to the same result as the author. But again I could be wrong.
wyChoong
wyChoong15mo ago
What I understand from the author is, there are 2 issues raised 1) duplicated queries 2) count from not current tenant are executed For the tenant part I’m have no comment as I don’t use tenancy in my app However the duplicate queries from count is due to the code the author copied so just to point it out So if he worked out how to cache the count it should reduce the queries and then the remaining issue is on the tenancy
mar5hall
mar5hall15mo ago
Yeap. I think you're right
laraveldev04523
laraveldev04523OP15mo ago
When I remove tenancy from the app, then the query runs twice as the query is in the code twice, which I completely get. It seems that for every tenant, the query runs twice. So, if I have 10 tenants, then the query runs 2x per tenant for a total of 20 queries.
wyChoong
wyChoong15mo ago
can you create an issue on github with a repo?
laraveldev04523
laraveldev04523OP15mo ago
That's a good idea. I can work on that and post a link when I have it ready.
Saade
Saade15mo ago
why not..
public static function getNavigationItems(): array
{
[$navigationItem] = parent::getNavigationItems();

$count = static::getModel()::count();

return [
$navigationItem
->badge($count, color: $count > 10 ? 'info' : 'gray'),
];
}
public static function getNavigationItems(): array
{
[$navigationItem] = parent::getNavigationItems();

$count = static::getModel()::count();

return [
$navigationItem
->badge($count, color: $count > 10 ? 'info' : 'gray'),
];
}
then you can remove getNavigationBadge and getNavigationBadgeColor and calculate the badge only once
wyChoong
wyChoong15mo ago
it would be easier to define a static::getModelCount that stored to a static variable and use it in both methods rather than hack around like this
Saade
Saade15mo ago
it would need to be a computed property, otherwise calling static::getModelCount() twice (one for the label and one for the color) would have the same result
wyChoong
wyChoong15mo ago
not tested but this should works, no?
static $badgeCount = null;

public static getModelCount():int{
return static::$badgeCount ??= static::getModel()::count();
}
static $badgeCount = null;

public static getModelCount():int{
return static::$badgeCount ??= static::getModel()::count();
}
Saade
Saade15mo ago
yeah, but that's a project-spacific code, i doubt it will be included into the core

Did you find this page helpful?