I wrote a code something like this:
$bunnies = Bunny::with(['carrots' => function ($query) use ($request){
if (empty($request->carrotStatus))
return;
$query->where('status', $request->carrotStatus);
}, 'owner'])
->select('bunnies.*')
->join('carrots', 'bunnies.id', '=', 'carrots.bunny_id')
->where(function (Builder $query) use ($request){
if (empty($request->carrotStatus))
return;
$query->where('carrots.status', $request->carrotStatus);
})
->where(function (Builder $query) use ($request) {
if (empty($request->multiSearch)) {
return;
}
$query
->orWhereLike('carrots.name', "%{$request->multiSearch}%")
->orWhereLike('bunnies.name', "%{$request->multiSearch}%");
})
->groupBy('bunnies.id')
->orderBy('bunnies.id', 'asc')
->paginate(
perPage: $request->get('pageSize', 5),
page: $request->get('page', 1)
);
It runs in strict mode. https://laravel-news.com/shouldbestrict
I wonder if it is possible to make it less ugly. I don’t like that I give the bunny type twice Bunny::
and ->select('bunnies.*')
and that I use table names instead of model names only. I don’t like the with
part, but I am not sure if it is possible to replace it to load
in strict mode. Can somebody help with these two?
2
Answers
I managed to solve this:
I replaced the
with
toload
, so I was able to separate the eager loading part from the query. After it I moved the!empty
conditions outside the closures. And finally I changed the uglyselect-join
towhereHas
which is in theory somewhat faster too. I was not able to use model names only, but it is not a real issue since Icarrots
is not a table name, but the relationship name here.you can break the query into multiple parts like this :
also you can use
if(!condition) { what you wanna do }
instead ofif(condition) return
then what you want to do under it 🙂