Laravel - красноречивое отношение, где есть одно или несколько других отношений - PullRequest
0 голосов
/ 24 января 2019

В данный момент я изучаю Laravel и Laravel eloquent, а сейчас пытаюсь решить проблему, используя отношения в Laravel. Это то, что я хочу архивировать:

База данных содержит множество спортивных клубов. В спортивном клубе много команд. У каждой команды есть игры. Таблица команд имеет столбец с именем club_id. Теперь я хочу создать красноречивые отношения, чтобы получить все игры клуба.

Вот что я получил до сих пор:

Клубная модель

id => PRIMARY

public function games()
    {
        return $this->hasMany('App\Models\Games')->whereHas('homeTeam')->orWhereHas('guestTeam');
    }

Игровая модель

home_id => FOREIGN KEY of team ; guest_id => FOREIGN KEY of team

public function homeTeam()
    {
        return $this->belongsTo('App\Models\Team','home_id')->where('club_id','=', $club_id);
    }

    public function guestTeam()
    {
        return $this->belongsTo('App\Models\Team','guest_id')->where('club_id','=', $club_id);
    }

Модель команды

id => PRIMARY ; club_id => FOREIGN

В моем контроллере все, что я хочу сделать, это Club::findOrFail($id)->games()

Выполнение приведенного выше кода возвращает ошибку SQL, что в таблице игр нет столбца с именем club_id.

Как правильно создать такое отношение?

Спасибо!

EDIT

Благодаря Никола Гаврику я нашел способ получить все Игры - но только там, где клубные команды являются домашней или выездной командой.

Вот соотношение:

public function games()
    {
        return $this->hasManyThrough('App\Models\Game','App\Models\Team','club_id','home_id');
    }

Как можно получить игры, в которых home_id ИЛИ guest_id совпадает с командой клуба? Последний параметр в этой функции не допускает массив.

Ответы [ 3 ]

0 голосов
/ 24 января 2019

Попробуйте это ...

Клубная модель

public function games()
    {
        return $this->hasMany('App\Models\Games');
    }

Игровая модель

public function homeTeam()
    {
        return $this->belongsTo('App\Models\Team','home_id');
    }

    public function guestTeam()
    {
        return $this->belongsTo('App\Models\Team','guest_id');
    }

Ваш запрос как

Club::where('id',$id)->has('games.guestTeam')->get();
0 голосов
/ 24 января 2019

Существует метод для извлечения "отдаленных отношений с посредником", и он называется Имеет много сквозных .

Существует также конкретный пример того, как его использовать, который включает Post, Country и User, но я думаю, что этого будет достаточно, чтобы дать вам подсказку о том, как создать games отношения внутри Club модель. Здесь - ссылка, но когда вы откроете ее, поищите ключевое слово hasManyThrough, и вы увидите пример.

P.S .: При правильном keys naming вы можете достичь этого с:

public function games()
{
    return $this->hasManyThrough('App\Models\Games', 'App\Models\Teams');
}

РЕДАКТИРОВАТЬ # 01

Поскольку у вас есть 2 типа команд, вы можете создать 2 разных отношения, где каждое отношение даст вам тот тип, который вам нужен. Как это:

public function gamesAsHome()
{
    return $this
        ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'home_id');
}

public function gamesAsGuests()
{
    return $this
        ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'guest_id');
}

РЕДАКТИРОВАТЬ # 02

Объединение отношений : Чтобы объединить эти 2 отношения, вы можете использовать метод merge() для экземпляра Collection, что он будет делать, он будет добавлять все записи из второй коллекции в первой .

$gamesHome = $model->gamesAsHome;
$gamesGuests = $model->gamesAsGuests;
$games = $gamesHome->merge($gamesGuests);

return $games->unique()->all();

Спасибо @HCK за указание на то, что у вас могут быть дубликаты после слияния и что unique() требуется для получения уникальных игр после слияния .


РЕДАКТИРОВАТЬ # 03

sortBy также предлагает callable вместо attribute name в случаях, когда Collection содержит numerical indexing. Вы можете отсортировать Collection так:

$merged->sortBy(function($game, $key) {
    return $game->created_at;
});
0 голосов
/ 24 января 2019

Когда вы определяете игры клуба hasMany, вы указываете, что в игре есть внешний ключ club_id, указывающий на клуб.belongsTo то же самое, но по-другому.Они должны быть согласованы с тем, что имеется в вашей базе данных, это означает, что вы должны определить эти ключи как внешние ключи в ваших таблицах.

...