Search in morph to many relationships

I have a Payment Resource. In the payment model, I have a morph to relationship with payee
/**
* Get the payee model ( Candidate / Student).
*/
public function payee() : MorphTo
{
return $this->morphTo();
}
/**
* Get the payee model ( Candidate / Student).
*/
public function payee() : MorphTo
{
return $this->morphTo();
}
In the table, I have a column in which I show the code of the payee. The code is like this
Tables\Columns\TextColumn::make('payee')
->label('Code')
->formatStateUsing(fn (Candidate|Student $state): string =>
($state instanceof Candidate)
? $state->registration_code
: $state->roll_no
)
Tables\Columns\TextColumn::make('payee')
->label('Code')
->formatStateUsing(fn (Candidate|Student $state): string =>
($state instanceof Candidate)
? $state->registration_code
: $state->roll_no
)
I want to make this column searchable. Is there a way to achieve it? I can only think of joining the tables in the Eloquent query and change the column definition using a case statement. But that is rather messy and would like to have a cleaner solution, if available. Thanks in advance for any help.
16 Replies
Husky110
Husky1102y ago
I think you have to use getStateUsing instead of formatStateUsing to make it searchable.
Anish
AnishOP2y ago
Nope, gives server error.
awcodes
awcodes2y ago
What is the error? My guess is that the relationship isn’t getting eager loaded.
Anish
AnishOP2y ago
Stack Trace
Unable to resolve dependency [Parameter #0 [ <required> App\Models\Candidate\Candidate|App\Models\Student\Student $state ]] in class App\Filament\Resources\Payment\PaymentRequestResource {"view":{"view":"/home/ubuntu/admission-2023/vendor/filament/tables/resources/views/columns/text-column.blade.php","data":[]},"userId":1,"exception":"[object] (Spatie\\LaravelIgnition\\Exceptions\\ViewException(code: 0): Unable to resolve dependency [Parameter #0 [ <required> App\\Models\\Candidate\\Candidate|App\\Models\\Student\\Student $state ]] in class App\\Filament\\Resources\\Payment\\PaymentRequestResource at /home/ubuntu/admission-2023/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:188)
Unable to resolve dependency [Parameter #0 [ <required> App\Models\Candidate\Candidate|App\Models\Student\Student $state ]] in class App\Filament\Resources\Payment\PaymentRequestResource {"view":{"view":"/home/ubuntu/admission-2023/vendor/filament/tables/resources/views/columns/text-column.blade.php","data":[]},"userId":1,"exception":"[object] (Spatie\\LaravelIgnition\\Exceptions\\ViewException(code: 0): Unable to resolve dependency [Parameter #0 [ <required> App\\Models\\Candidate\\Candidate|App\\Models\\Student\\Student $state ]] in class App\\Filament\\Resources\\Payment\\PaymentRequestResource at /home/ubuntu/admission-2023/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:188)
May be I am doing something wrong. I have replaced formatStateUsing by getStateUsing. Not even added ->searchable(). This itself is giving server error.
Husky110
Husky1102y ago
Try this:
->getStateUsing(fn ($record): string =>
($record->payee instanceof Candidate)
? $record->payee->registration_code
: $record->payee->roll_no
)
->getStateUsing(fn ($record): string =>
($record->payee instanceof Candidate)
? $record->payee->registration_code
: $record->payee->roll_no
)
awcodes
awcodes2y ago
$state won’t be an instance of the model. It will be an array. That’s why it’s a dependency injection error.
Anish
AnishOP2y ago
Unfortunately this does not work. Only this shows the table correctly. Now I added searchable and when I tried to search again gives server error.
Husky110
Husky1102y ago
hmm - the last thing that pops to my mind would be enhancing the getTableQuery()-function with with(['payee']) and try again.
Anish
AnishOP2y ago
This also does not work. However, if I just do
Tables\Columns\TextColumn::make('payee.registration_code')
Tables\Columns\TextColumn::make('payee.registration_code')
This seems to work only for the Candidate model. So, I am splitting the column into two : registration_code and roll_no. Then it works separately on each models.
Husky110
Husky1102y ago
I just read the docs again - and you can actually do a Closure in the searchable-function! (see https://filamentphp.com/docs/2.x/tables/columns/getting-started#searching ) -> so you could do that and be like "whereHas()" and subquery that...
Filament
Getting started - Columns - Table Builder - Filament
The elegant TALL stack table builder for Laravel artisans.
Anish
AnishOP2y ago
Nope! Works for only one.
Husky110
Husky1102y ago
aaaaah I don't think so... 😁
Anish
AnishOP2y ago
That's great. I will try it out.
Husky110
Husky1102y ago
TextColumn::make('payee_whatever')
->searchable(query: function (Builder $query, string $search): Builder {
return $query
->whereOr('payee.registration_code', 'like', "%{$search}%")
->whereOr('payee.roll_no', 'like', "%{$search}%");
})
TextColumn::make('payee_whatever')
->searchable(query: function (Builder $query, string $search): Builder {
return $query
->whereOr('payee.registration_code', 'like', "%{$search}%")
->whereOr('payee.roll_no', 'like', "%{$search}%");
})
or something along those lines should do the trick ^^ I would actually add a column to the main-model to cercumvent that morphTo-Cluster-F cause even tho it is possible to build a search-query, it will be complete horse-💩 performance-wise... 😄
Anish
AnishOP2y ago
This is what finally I come up with which works
->searchable(
query: fn (Builder $query, string $search): Builder
=> $query
->orWhereMorphRelation(
relation: 'payee',
types:[Candidate::class],
column:'registration_code',
operator:'like',
value:"%{$search}%"
)
->orWhereMorphRelation(
relation: 'payee',
types:[Student::class],
column:'roll_no',
operator:'like',
value:"%{$search}%"
)
)
->searchable(
query: fn (Builder $query, string $search): Builder
=> $query
->orWhereMorphRelation(
relation: 'payee',
types:[Candidate::class],
column:'registration_code',
operator:'like',
value:"%{$search}%"
)
->orWhereMorphRelation(
relation: 'payee',
types:[Student::class],
column:'roll_no',
operator:'like',
value:"%{$search}%"
)
)
Thanks for the tip. I will try it.
Husky110
Husky1102y ago
Yay - good luck! 🙂
Want results from more Discord servers?
Add your server