You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Have you published the resource files and customized them? (php artisan vendor:publish)
No
What is the problem?
The filterRelation(string $relation, string $field) method, inherited from FilterBase, provides a convenient way to define filters that target columns on related models. This method works as expected when used with Filter::inputText(), correctly generating WHERE HAS or whereRelation clauses.
However, when filterRelation() is called on a Filter::select() instance, the logic within PowerComponents\LivewirePowerGrid\Components\Filters\Builders\Select.php (specifically its builder() method) does not appear to check for or utilize the filterRelation properties. Instead, it proceeds to its default filtering logic (applying a WHERE clause on the main query using the filter's $field) or uses a custom ->builder(Closure) if provided.
This inconsistency forces users to manually implement the WHERE HAS logic using FilterSelect->builder(Closure) for scenarios where FilterInputText->filterRelation() would have handled it automatically with a simpler definition. While the ->builder(Closure) workaround is effective, making filterRelation() functional for FilterSelect would improve consistency and ease of use.
Code snippets
Let's consider a scenario with Vehicle and Engine models:
A Vehicle model (main model for the PowerGrid table).
An Engine model, related to Vehicle via a MorphOne or HasOne relationship (e.g., public function engine() { return $this->morphOne(Engine::class, 'owner'); }).
The Engine model has a status column (e.g., values like 'new', 'used', 'rebuilt').
We want to filter Vehicle records based on their engine.status using a select dropdown.
// In your PowerGrid Componentpublicfunctiondatasource(): Builder
{
returnApp\Models\Vehicle::query()->with('engine');
}
publicfunctionfields(): PowerGridFields
{
return PowerGrid::fields()
->add('id')
->add('engine.status', fn ($vehicle) => $vehicle->engine?->status)
->add('name');
}
publicfunctioncolumns(): array
{
return [
Column::make('ID', 'id'),
Column::make('Vehicle Name', 'name')->searchable(),
Column::make('Engine Status', 'engine.status')->searchable(),
];
}
// Optional, for global search, but filterRelation should ideally handle specific filterpublicfunctionrelationSearch(): array
{
return [
'engine' => ['status'],
];
}
The alternative code that does work, and shows that the belowshould work:
// In filters() method
Filter::inputText('engine.status') // $field 'status' on the relation
->filterRelation('engine', 'status') // Targets 'status' column on 'engine' relation
The code that does not work, but should work (THE PROBLEM):
// In filters() method
Filter::select('engine.status') // $columnName, $field (conceptual target on relation)
->dataSource(collect([
['engine_state' => 'new', 'name' => 'New Engine'],
['engine_state' => 'used', 'name' => 'Used Engine'],
['engine_state' => 'rebuilt', 'name' => 'Rebuilt Engine'],
]))
->optionValue('engine_state')
->optionLabel('name')
->filterRelation('engine', 'status') // <<< THIS CALL IS MADE, BUT SEEMS TO HAVE NO EFFECT ON SQL
Observed SQL: The query generated for this FilterSelect (if no custom builder closure is provided) tends to be something like WHERE vehicles.status = 'new' or WHERE status = 'new' (applied to the main vehicles table), not a WHERE HAS engine (...). Source Code Indication:
FilterBase.php defines public function filterRelation(...) and the $filterRelation property.
PowerComponents\LivewirePowerGrid\Components\Filters\Builders\InputText.php (in its builder method) explicitly checks for data_get($this->filterBase, 'filterRelation') and uses it.
PowerComponents\LivewirePowerGrid\Components\Filters\Builders\Select.php (in its builder method) only checks for data_get($this->filterBase, 'builder') (for a custom closure) and then applies its default logic. It does not appear to check for or use the filterRelation properties.
Current workaround:
// In filters() method
Filter::select('engine.status')
->dataSource(collect([
['engine_state' => 'new', 'name' => 'New Engine'],
['engine_state' => 'used', 'name' => 'Used Engine'],
]))
->optionValue('engine_state')
->optionLabel('name')
->builder(function (Builder$query, $value) { // Note: Closure takes 2 argumentsif (!is_null($value) && $value !== '') {
// Ensure $value is used correctly, could be single or array depending on select type$actualValue = is_array($value) ? ($value[0] ?? null) : $value;
if (!is_null($actualValue) && $actualValue !== '') {
$query->whereHas('engine', function ($subQuery) use ($actualValue) {
$subQuery->where('status', $actualValue); // 'status' is column on Engine model
});
}
}
return$query;
})
How do you expect it to work?
It would be expected that Filter::select(...)->filterRelation('engine', 'status') would function similarly to its FilterInputText counterpart. The PowerComponents\LivewirePowerGrid\Components\Filters\Builders\Select.php class should ideally:
Check if filterRelation data is present on the FilterSelect instance.
If present, prioritize this and construct the appropriate WHERE HAS (or whereRelation) query, using an = operator for the comparison (suitable for select filters).
This would make filtering on relationships using FilterSelect more declarative and consistent with other filter types, reducing the need for manual builder closures for common relational filtering tasks.
Please confirm (incomplete submissions will not be addressed)
I have provided easy and step-by-step instructions to reproduce the bug.
I have provided code samples as text and NOT images.
I understand my bug report will be removed if I haven't met the criteria above.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Livewire PowerGrid version
v6.3.2
Livewire version
v3.6.3
Laravel version
v10.38.0
Which PHP version are you using?
PHP 8.3
Which Theme are you using?
Bootstrap 5
Have you published the resource files and customized them? (php artisan vendor:publish)
No
What is the problem?
The filterRelation(string $relation, string $field) method, inherited from FilterBase, provides a convenient way to define filters that target columns on related models. This method works as expected when used with Filter::inputText(), correctly generating WHERE HAS or whereRelation clauses.
However, when filterRelation() is called on a Filter::select() instance, the logic within PowerComponents\LivewirePowerGrid\Components\Filters\Builders\Select.php (specifically its builder() method) does not appear to check for or utilize the filterRelation properties. Instead, it proceeds to its default filtering logic (applying a WHERE clause on the main query using the filter's $field) or uses a custom ->builder(Closure) if provided.
This inconsistency forces users to manually implement the WHERE HAS logic using FilterSelect->builder(Closure) for scenarios where FilterInputText->filterRelation() would have handled it automatically with a simpler definition. While the ->builder(Closure) workaround is effective, making filterRelation() functional for FilterSelect would improve consistency and ease of use.
Code snippets
Let's consider a scenario with Vehicle and Engine models:
We want to filter Vehicle records based on their engine.status using a select dropdown.
The alternative code that does work, and shows that the belowshould work:
The code that does not work, but should work (THE PROBLEM):
Observed SQL: The query generated for this FilterSelect (if no custom builder closure is provided) tends to be something like WHERE vehicles.status = 'new' or WHERE status = 'new' (applied to the main vehicles table), not a WHERE HAS engine (...).
Source Code Indication:
Current workaround:
How do you expect it to work?
It would be expected that Filter::select(...)->filterRelation('engine', 'status') would function similarly to its FilterInputText counterpart. The PowerComponents\LivewirePowerGrid\Components\Filters\Builders\Select.php class should ideally:
Please confirm (incomplete submissions will not be addressed)
Beta Was this translation helpful? Give feedback.
All reactions