Красноречивый с вложенными

В настоящее время у меня есть это whereHas в коллекции моей модели:

$query = self::whereHas('club', function($q) use ($search) { $q->whereHas('owner', function($q) use ($search) { $q->where('name', 'LIKE', '%'. $search .'%'); }); }); 

Мне показалось, что код выше может быть таким:

 $query = self::whereHas('club.owner', function($q) use ($search) { $q->where('name', 'LIKE', '%'. $search .'%'); }); 

Я знаю, что это уже много сил, но даже тогда, если у меня вложенные отношения на 5 уровней глубоко, все станет некрасиво.

Обновить:

Как указано в комментариях, я в конечном итоге не поставил свой вопрос ясным, извиняюсь.

Я попытаюсь использовать простой пример, рассмотрим $owner->club->membership->product->package , теперь от владельцев, которых я хочу найти в определенном пакете, это будет примерно так:

 $query = self::whereHas('club', function($q) use ($search) { $q->whereHas('membership', function($q) use ($search) { $q->whereHas('product', function($q) use ($search) { $q->whereHas('package', function($q) use ($search) { $q->where('alias', 'LIKE', '%'. $search .'%'); });//package });//product });//membership });//club 

Это верно? Есть ли ярлык?

Обновление: PR был просто объединен с 4.2, так что теперь можно использовать точечную вложенную нотацию в методах ( ->has('relation1.relation2) ->whereHas('relation1.relation2, .. )

Ваш вопрос остается немного неясным, или вы неправильно понимаете метод whereHas (), поскольку он используется для фильтрации моделей (в этом случае пользователи) и получают только те, у которых соответствующие модели соответствуют условиям поиска.

Кажется, что вы хотите найти Пакеты из контекста данного Пользователя , поэтому нет необходимости использовать метод whereHas.

Во всяком случае, в зависимости от отношений (1-1,1-м, мм) это может быть легко или довольно сложно и не очень эффективно. Как я уже сказал, загрузка вложенных отношений означает, что для каждого уровня вложенности приходит другой запрос db, поэтому в этом случае вы получаете 5 запросов.

Независимо от отношений вы можете инвертировать эту цепочку так, как это будет легче:


edit: Это не будет работать atm, так как whereHas () не обрабатывает отношения вложенных точек!

 // given $user and $search: $packages = Package::where('alias','like',"%$search%") ->whereHas('product.membership.club.user', function ($q) use ($user) { $q->whereId($user->id); })->get(); 

Как вы можете видеть, это гораздо более читаемо, все еще выполняется 5 запросов. Также вы получаете $ packages, который представляет собой единую коллекцию моделей, которые вы хотели.

Хотя из контекста пользователя вы получите что-то вроде этого (в зависимости от отношений снова):

 $user |-club | |-membership | | |-product | | | |-packages | | |-anotherProduct | | | |-packages | | |-yetAnotherProduct | | |-packages | |-anotherMembership ..... 

Вы понимаете, не так ли?

Вы можете получить пакеты из коллекции, но это было бы громоздким. Все наоборот.

Таким образом, ответ на ваш вопрос будет просто присоединяться к таблицам:

 // Let's assume the relations are the easiest to handle: 1-many $packages = Package::where('alias','like',"%$search%") ->join('products','packages.product_id','=','products.id') ->join('memberships','products.membership_id','=','memberships.id') ->join('clubs','memberships.club_id','=','clubs.id') ->where('clubs.user_id','=',$user->id) ->get(['packages.*']); // dont select anything but packages table 

Конечно, вы можете обернуть его красивым методом, поэтому вам не нужно писать это каждый раз, когда вы выполняете такой поиск. Выполнение этого запроса будет, безусловно, намного лучше, чем отдельные 5 запросов, показанных выше. Очевидно, таким образом вы загружаете только пакеты без других связанных моделей.