F
Filament16mo ago
gizmojo

Eager loaded relationship based on table filter

I'm trying to load a relationship based on the table filter. In v2 I could do this but in v3 throws error:
Typed property Filament\Widgets\TableWidget::$table must not be accessed before initialization
protected function getTableQuery(): Builder
{
$filter_language = $this->getCachedTableFilter('language_id') ?? null;

return Product::when(
$filter_language,
fn (Builder $query, $language_id): Builder => $query->withWhereHas('language', fn ($query) => $query->where('id', $language_id)),
)
->when(
! $filter_language,
fn (Builder $query): Builder => $query->with('language', fn ($query) => $query->where('default', 1)),
);
}
protected function getTableQuery(): Builder
{
$filter_language = $this->getCachedTableFilter('language_id') ?? null;

return Product::when(
$filter_language,
fn (Builder $query, $language_id): Builder => $query->withWhereHas('language', fn ($query) => $query->where('id', $language_id)),
)
->when(
! $filter_language,
fn (Builder $query): Builder => $query->with('language', fn ($query) => $query->where('default', 1)),
);
}
When I switch over to using table method with filters the when is called but the eager relationship is never loaded causing error:
Attempted to lazy load [language] on model
$table->columsn([])
->filters([
Tables\Filters\SelectFilter::make('language_id')
->options(fn () => Language::options())
->query(function (Builder $query, $state): Builder {
// Or simplified down to this doesn't get eager loaded
// return $query->with('language');

$language_id = $state['value'] ?? null;

return $query
->when(
$language_id,
fn (Builder $query, $language_id): Builder => $query->withWhereHas('language', fn ($query) => $query->where('id', $language_id)),
)
->when(
! $language_id,
fn (Builder $query): Builder => $query->with('language', fn ($query) => $query->orderByRaw('FIELD(`default`, 0), `name` ASC')),
);
})
$table->columsn([])
->filters([
Tables\Filters\SelectFilter::make('language_id')
->options(fn () => Language::options())
->query(function (Builder $query, $state): Builder {
// Or simplified down to this doesn't get eager loaded
// return $query->with('language');

$language_id = $state['value'] ?? null;

return $query
->when(
$language_id,
fn (Builder $query, $language_id): Builder => $query->withWhereHas('language', fn ($query) => $query->where('id', $language_id)),
)
->when(
! $language_id,
fn (Builder $query): Builder => $query->with('language', fn ($query) => $query->orderByRaw('FIELD(`default`, 0), `name` ASC')),
);
})
Tried to access the filter via livewire $table->getLivewire()->getTableFilterState('language_id') but this causes a recursive loop 500 error. Also tried $this->getTableFilterState('language_id')['value'] ?? null;
1 Reply
gizmojo
gizmojoOP16mo ago
I see why I can't use eager loading from inside a filter query now because they are wrapped in a where clause. Still not sure how I would get the table filter from inside query() Digging into Filters I see there's modifyBaseQueryUsing exactly what I needed working perfectly now.
Want results from more Discord servers?
Add your server