Красноречивые отношения с условной областью - PullRequest
0 голосов
/ 30 апреля 2019

Я работаю над спортивным приложением Fantasy.Модели, с которыми я работаю, это FantasyPlayer, PlayerGame, TeamGame

FantasyPlayer может иметь много PlayerGame и много TeamGame

public function PlayerGame()
{
    return $this->hasMany('App\Models\PlayerGame','player_id','player_id');
}

public function TeamGame()
{
    return $this->hasMany('App\Models\FantasyData\TeamGame','team','fantasy_player_key');
}

Когда я загружаю данные, которые я использую в настоящий момент, загружается в настоящее время:

FantasyPlayer::with(['PlayerGame', 'TeamGame'])->take(1)->get();

Становится утомительным загружать оба отношения, а затем загружать их.В идеале, я хочу, чтобы модель обрабатывала эту логику.Поэтому я мог бы сделать что-то вроде этого:

FantasyPlayer::with(['FantasyGame'])->take(1)->get();

Тогда моя область видимости FantasyGame будет содержать либо нужную мне запись PlayerGame, либо TeamGame, основанную на значении FantasyPlayer для позиции.Что-то вроде этого - то, что я хочу ... но у меня это не работает:

public function scopeFantasyGame($query)
{
    if($this->position == "DEF"){
      return $this->TeamGame();
    }
    else{
      return $this->PlayerGame();
    }
 }

Кто-нибудь знает, как я могу использовать нетерпеливую загрузку и заставить FantasyGame вернуть правильные отношения, основанные на позиции FantasyPlayer?атрибут?:

FantasyPlayer::with(['FantasyGame'])->take(1)->get();

1 Ответ

1 голос
/ 30 апреля 2019

# 1

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

# FantasyPlayer.php

public function scopeFantasyGame($query)
{
    if($this->position == "DEF") // <--- Laravel doens't retrieve the records yet,
    {                            //      so this won't work
      //
    }
    else
    {
      // 
    }
 }

# 2

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

# FantasyPlayer.php

public function scopeFantasyGame($query)
{
    return $query->with(['PlayerGame', 'TeamGame']);
}

Тогда используйте это так:

# YourController.php

public function myFunction($query)
{
    $fantasyPlayers = FantasyPlayer::fantasyGame()->get();
}

# 3

Но тогда, если вы хотите всегда загружать отношения, зачем использовать область запроса, а не просто указывать laravel, чтобы загрузить нужные отношения по умолчанию? Вы можете указать это в своей модели (отметьте Eager Загрузка по умолчанию из этого раздела документов):

# FantasyPlayer.php

protected $with = ['PlayerGame', 'TeamGame'];

Обновление

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

# FantasyPlayer.php

public function scopeHasFantasyGame($query)
{
    return $query
              ->has('PlayerGame')
              ->has('TeamGame');
}

Тогда:

# YourController.php

public function myFunction($query)
{
    $fantasyPlayers = FantasyPlayer::hasFantasyGame()->get();
}

Второй вариант - получить элементы, а затем отфильтровать коллекцию на основе существования взаимосвязи (используя функцию Map () ):

# YourController.php

public function myFunction($query)
{
    $fantasyPlayers = FantasyPlayer::all()
                          ->map(function ($fantasyPlayer) {
                              return $fantasyPlayer->PlayerGame()->exists()
                                     && $fantasyPlayer->TeamGame()->exists();
                          });
}
...