spatie / laravel-query-builder

Easily build Eloquent queries from API requests
https://spatie.be/docs/laravel-query-builder
MIT License
4k stars 392 forks source link

Error accessing field in multi-level nested relationship #874

Closed wonder95 closed 1 year ago

wonder95 commented 1 year ago

I am attempting to do some filtering using a multi-level nested relationship (User-> Dues ->Payment is the model hierarchy), like so.

        return Inertia::render('TreasuryReport', [
            'payments' => QueryBuilder::for(Payment::class)
                ->with('dues.user')
                ->allowedFields('dues.user.first_name', 'dues.user.last_name')
                ->allowedFilters([
                    AllowedFilter::exact('mode'),
                    AllowedFilter::callback('name', function(Builder $query, $value) {
                        $query->where('dues.user.first_name', 'like', "%{$value}%")
                            ->orWhere('dues.user.last_name', 'like', "%{$value}%");
                    })
                ])
                ->orderBy('payment_date', 'desc')
                ->paginate(15)
                ->withQueryString()
        ]);

but I get the following error

  SQLSTATE[42S22]: Column not found: 1054 Unknown column 'dues.user.first_name' in 'where clause' 

select count(*) as aggregate from `payments` where (`dues`.`user`.`first_name` like %Smith% or `dues`.`user`.`last_name` like %Smith%) and `deleted_at` is null

From what I read in the docs and this past issue, this should work.

Am I doing something wrong, or is this indeed a bug?

wonder95 commented 1 year ago

Thanks to Larry AI at Laracasts, I found out that I just needed to add whereHas() to my query

use Illuminate\Database\Eloquent\Builder;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\QueryBuilder;

return Inertia::render('TreasuryReport', [
    'payments' => QueryBuilder::for(Payment::class)
        ->with('dues.user')
        ->allowedFields('dues.user.first_name', 'dues.user.last_name')
        ->allowedFilters([
            AllowedFilter::exact('mode'),
            AllowedFilter::callback('name', function (Builder $query, $value) {
                $query->whereHas('dues.user', function (Builder $query) use ($value) {
                    $query->where('first_name', 'like', "%{$value}%")
                        ->orWhere('last_name', 'like', "%{$value}%");
                });
            })
        ])
        ->orderBy('payment_date', 'desc')
        ->paginate(15)
        ->withQueryString()
]);