Итак, вы пытаетесь получить одного пользователя, но со своими игроками (где пользователи bTM-игроков) уже заполнены и упорядочены по положению (где позиция поворота bT).
В этом случае вы не сможете использовать встроенные методы взаимоотношений Laravel без изменений, потому что Laravel просто не был создан для отношений, которые находятся на сводной таблице других отношений. К счастью, ORM достаточно гибкий, чтобы позволить вам делать то, что вы хотите, с помощью «ручного» соединения.
Так, чтобы ответить на ваш вопрос прямо, вот код вида вам требуется (вы были очень близки!):
$user = User::with(['players' => function ($q) {
$q->join('position', 'league_player_user.position_id', '=', 'position.id')
->orderBy('position.sort_id', 'asc');
}])->where('id', Auth::user()->id)->first();
Тем не менее, мне кажется, что это не большой код по нескольким причинам:
- Вы вручную получение авторизованного пользователя (когда
Auth::user()
является так удобно)
- Вы на самом деле того, чтобы принять логику реализации конкретной из я (тот факт, что сводная таблица называется
league_player_user
и помещает ее ... ну где бы это ни было (ваш контроллер?)
- Это затронет только один единственный запрос - если вам случится получить
User
каким-либо другим способом (например Auth::user()
или User::find(1)
или любой другой), вы не будете иметь игрок правильно
упорядоченных Таким образом, я мог бы предположить, что для целей делают ваш запрос более просто вы не нетерпеливые нагрузок игроков.Таким образом, все, что вам нужно сделать, это заранее:
$user = Auth::user();
Теперь на отношения (игроки() метод в классе User
) вы делаете специальное упорядочение работы:
public function players()
{
return $this->belongsToMany('App\Models\Player', 'league_player_user')
->withPivot('position_id')
->join('position', 'league_player_user.position_id', '=', 'position.id')
->orderBy('position.sort_id');
}
Таким образом, в любое время, когда вы звоните $user->players
, вы получите их правильно.
Я должен просто добавить, что выполнение этого способа может не позволить вам загружать игроков, как желательная загрузка Laravel (т. Е. Используя ->with()
в цепочке ORM) из-за того, что Laravel выполняет загружаемые запросы загрузки - один для основной запрос (т.е. пользователи) и один для отношений (т. е. игроков), но он делает этот запрос для получения всех результатов, поэтому, возможно, не будет работать с специальной системой заказа. Вам нужно будет увидеть, действительно ли вы волнуете загрузку игроков. В вашем случае выше (где вы получаете единственного авторизованного пользователя), на мой взгляд, интересная загрузка не так важна.
Редактировать, чтобы добавить разъяснения относительно нетерпеливого загрузки:
Мои рассуждения позади предполагая, что жадную загрузку не может работать, что жадная загрузка в Laravel делается вроде как это: у вас есть категории и продукты: Category
Hm Product
, Product
bT Category
. Чтобы получить категорию, вы используете $category = Category::find(1)
, а Laravel превращает это в запрос примерно так: SELECT * FROM `categories` WHERE `id` = '1'
. Если вы тогда позвоните $category->products
, то Laravel выдает SELECT * FROM `products` WHERE `category_id` = '1'
. Это разумно. Но если вы имели следующий код, было бы хуже:
<?php $categories = Category::all(); ?>
<ul>
@foreach ($categories as $category)
<li>Category {{{ $category->name }}} contains {{{ $category->products->count() }}} products.</li>
@endforeach
</ul>
В этом случае вы имеете следующие вопросы:
SELECT * FROM `categories`;
SELECT * FROM `products` WHERE `category_id` = '1';
SELECT * FROM `products` WHERE `category_id` = '2';
SELECT * FROM `products` WHERE `category_id` = '3';
... as many categories as you had
Однако, если вы должны были изменить эту первую строчку в этом :
<?php $categories = Category::with('products')->get(); ?>
Теперь вы бы только два запроса:
SELECT * FROM `categories`;
SELECT * FROM `products` WHERE `category_id` IN ('1', '2', '3', ...);
Laravel затем, после вызова второго запроса, создаст для вас различные коллекции на основе идентификаторов категорий, которые, как он знает, у вас есть.
Однако, это упрощенный случай отношений. В вашем случае метод products()
не является только return $this->hasMany('Product');
, но включает в себя свод и ручное соединение и т. Д., И вполне возможно, что этот второй запрос, который является загружаемым, просто не сможет справиться и сделать это упорядочивая правильно.
Как я уже сказал, я точно не знаю, как это работает, для меня это всего лишь красный флаг. Во что бы то ни стало дайте ему понять, что вы получаете - вы можете обнаружить, что он работает для вас.
'ownToMany' в вашей модели User будет автоматически присоединяться к сводной таблице (и к далекой таблице (' игроки')), но не будет входить в таблицу 'position' (даже если вы говорите, что хотите' position_id 'column. Таким образом, вам нужно убедиться, что вы добавите дополнительное соединение самостоятельно. Я думаю, вы можете сделать это с помощью' User :: with ('players', 'players.position') '(хотя, поскольку' position_id' является виртуальным поле из опорных отношений, вы, возможно, не сможете это сделать, вам придется играть с кодом). Дело в том, что 'position' не присоединяется автоматически, поэтому вы не можете заказать на нем – alexrussell
Спасибо @alexrussell.Я посмотрел на это, да, и я тоже хочу загрузить вложенное отношение. И тогда я могу запросить orderBy() в файле players.position, и хотя он не является ошибкой, он корректно не сортирует результаты. – Alex
Вместо использования '-> first()' use '-> toSql () ', чтобы вернуть SQL, который он генерирует, - это поможет вам отлаживать то, что подходит ORM. – alexrussell