Использование специальных функций объединения внутри модели Laravel Eloquent

Я начал разрабатывать веб-сайт с использованием Laravel, и я почти все нахожу через официальную документацию и ответы, которые я нахожу здесь. Однако есть одна вещь, которую - хотя я нашел способ сделать - у меня есть ощущение, что это можно сделать другим, более оптимизированным способом, чем тот, который я делаю прямо сейчас. Позволь мне объяснить.

На моем веб-сайте у меня есть таблица под названием «игроки», в которой содержатся данные о некоторых игроках, извлеченные из футбольного матча. Допустим, структура такая:


ID (int, первичный ключ, A_I)

GameID (int, unique) // что использует игра

Имя игрока

Данные (в основном много разных столбцов)


Поскольку цель моего веб-сайта - позволить пользователям вносить изменения в контент игры, у меня также есть еще одна таблица, которую я называю «userplayers», которую я использую для внесения изменений в игроков, которые существуют в исходной таблице, или для добавления новые. Структура похожа на таблицу «игроков», но только с одним добавленным столбцом, называемым идентификатором пользователя, который должен определять, какая модификация принадлежит какому пользователю.


ID (int, первичный ключ, A_I)

GameID (int, уникальный вместе с userID)

Имя игрока

Данные (в основном много разных столбцов)

UserID (int, уникальный вместе с GameID)


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

Если пользователь не вошел в систему, я просто возвращаю таблицу игроков.

Используя красноречивую модель laravel, я могу легко получить таблицу игроков, когда пользователь не вошел в систему. Однако я не могу найти эффективный способ вернуть всю БД + созданный пользователем контент, просто используя основные функции красноречивой модели.

Раньше (без Laravel) я использовал этот запрос к БД:

SELECT * FROM (SELECT *, NULL FROM players WHERE NOT EXISTS (SELECT * FROM userplayers WHERE players.gameid=userplayers.gameid AND userId=$userId) UNION (SELECT * FROM userplayers WHERE userId=$userId)) AS pl;

И способ, которым я «нашел» что-то подобное в Laravel, - это добавление локальной области видимости внутри модели Players следующим образом:

public function scopeIncludeCustom($query, $user)
{
    return \DB::select('SELECT * FROM (SELECT *, NULL FROM players WHERE NOT EXISTS (SELECT * FROM userplayers WHERE userplayers.gameid=players.gameid AND userId='.$user.') UNION (SELECT * FROM userplayers WHERE userId='.$user.')) AS players_full);
}

Однако вы можете понять, что это не возвращает $ query, как предполагалось областями, а просто массив php, который я возвращаю обратно, и я думаю, что это неправильный способ сделать это. Например, когда я просто ищу в таблице игроков (без использования содержимого, созданного пользователем), для возврата результатов требуется гораздо меньше времени, чем для возврата результатов с настраиваемым содержимым.

Любые идеи очень ценятся.

Уже определились модели Player и UserPlayer? Вы знакомы с Eloquent Relations и whereHas()?

Jonas Staudenmeir 27.10.2018 19:02

@JonasStaudenmeir Да, я определил обе эти модели, но я, кажется, не понимаю, как я могу представить указанный выше синтаксис mysql через отношения, такие как whereHas()

Panos Paschalis 28.10.2018 12:34

Вы можете использовать запрос UNION с Eloquent, но все результаты будут экземплярами модели Player: если вам нужны экземпляры Player и UserPlayer, вы должны выполнять отдельные запросы.

Jonas Staudenmeir 28.10.2018 17:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
832
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Итак, давайте рассмотрим это шаг за шагом.


У меня была модель «Игрок», которая извлекала данные из таблицы «игроки».

У меня также была модель «Пользователь», которая извлекала данные из таблицы «пользователи».


Мне пришлось создать связь между этими двумя моделями. Запись в таблице «игроки» может иметь много записей, связанных с ними в таблице «пользователи». Итак, в модели Игрок я добавил это:

public function userplayers()
{
    return $this->hasMany('App\Userplayer', 'gameid', 'gameid');
}

В модели Пользователь я добавил это:

public function player()
{
    return $this->belongsTo('App\Player', 'gameid', 'gameid');
}

При запросе данных первым шагом было удаление каждой строки из таблицы «игроки», которая имела такой же «GameId», что и любая строка, возвращенная из таблицы «пользователи», которая также имела ограничение, что «userId» в каждой строке эта таблица должна быть конкретной.

Это код, который делает это в моем SearchPlayerController:

$orig_players = \App\Player::whereDoesntHave('userplayers', function ($query) use($user) 
{
    $query->where('userId', $user);
})->get();

В то же время мне нужно получить каждую строку из таблицы "userplayers", в которой есть "ID пользователя", который я хочу

$userplayers = \App\Userplayer::where([
                ['pesid', $search]
            ])->get();

Теперь я просто объединяю 2 результата (я не могу использовать UNION, потому что данные, которые я получаю из таблицы «игроки», имеют на один столбец меньше).

$players = $orig_players->merge($userplayers)
            ->sortBy('registeredName')
            ->take($limit);

И все работает отлично и намного быстрее, чем раньше!

Другие вопросы по теме