Laravel 5.6 withCount и оператор where

Я использую ларавель 5.6.

У меня есть 3 таблицы: игроки, игры и таблица game_player.

Получить количество игр каждого игрока легко с помощью действия index PlayersController:

//Get game count of every player
$players = Player::withCount('games')->get();

Есть ли способ получить количество игр для игр, когда игрок выиграл игру? (в действии index контроллера игроков) я не знаю, как это сделать. Кто-нибудь может помочь?

перенос игровых столов

$table->integer('winner')->unsigned()->index();
$table->foreign('winner')->references('id')->on('players')->onDelete('cascade');

введите здесь описание изображения

Миграция таблицы game_player

table->integer('game_id')->unsigned()->nullable();
$table->foreign('game_id')->references('id')->on('games')->onDelete('cascade');

$table->integer('player_id')->unsigned()->nullable();
$table->foreign('player_id')->references('id')->on('players')->onDelete('cascade');

введите здесь описание изображения

связь модели игры

public function players(){
    return $this->belongsToMany('App\Player')->withTimestamps();
}

//this is for the winner of the game
public function player()
{
    return $this->hasOne('App\Player');
}

отношение модели игрока

public function games(){
    return $this->belongsToMany('App\Game')->withTimestamps();
}

//the game the player has won
public function game()
{
    return $this->belongsTo('App\Game');
}

контроллер игроков

public function index()
{
    $players = Player::all();

    //Get game count of every player
    $players = Player::withCount('games')->get();

    /*Load the view and pass the groups*/
    return \View::make('players.index')->with('players', $players);
}

Результат, который я хочу, состоит в том, чтобы играть в игры (работает) и выигрывать игры.

результат

игрок > указательный нож

@foreach($players as $player)
   <p>{{ $player->id }}</p>
   <p>{{ $player->firstname }} {{ $player->lastname }}</p>
   <ul>
      <li>Played games: {{ $player->games_count }}</li>
      <li>Won games: </li>
   </ul>
@endforeach

обновить

Я не думаю, что мы можем рассматривать это как дубликат этого вопроса (Laravel использует предложение where в методе withCount), потому что я также использую отношения «многие ко многим».

Если я использую этот код, который не является правильным, потому что 1 должен быть динамическим $id:

$players = Player::withCount('games')
     ->having('winner', '=', 1)
     ->get();

Я получаю сообщение об ошибке:

SQLSTATE[42S22]: Столбец не найден: 1054 Неизвестный столбец «победитель» в «содержащем предложении» (SQL: выберите players., (выберите количество () из games внутреннего соединения game_player на games.id = game_player .game_id где players.id = game_player.player_id) как games_count из players с winner = 1)

обновление 2

Когда я использую этот код:

контроллер

$players = Player::all();

//Get game count of every player
$players = Player::withCount('games')->get();

$wongames = Player::withCount(['games' => function($query) { $query->where('winner', '=', 5); }])->get();

//$players = Player::withCount('games')->where('winner', '=', 1);

/*Load the view and pass the groups*/
return \View::make('players.index')->with('players', $players)->with('wongames', $wongames);

индекс лезвия

@foreach($players as $player)
   <p>{{ $player->id }}</p>
   <p>{{ $player->firstname }} {{ $player->lastname }}</p>
   <ul>
      <li>Played games: {{ $player->games_count }}</li>
         @foreach($wongames as $wongame)
            <li>Won games: {{ $wongame->games_count }}</li>
         @endforeach
   </ul>
@endforeach

Я получаю это (не то, что я точно хочу, но я думаю, что туда доберусь):

введите здесь описание изображения


person Gilko    schedule 16.04.2018    source источник
comment
Возможный дубликат Laravel с использованием предложения where в методе withCount   -  person Phiter    schedule 16.04.2018
comment
Попробуйте Player::withCount(['games' => function($query) { $query->where('winner', '=', 1); }]. Логика та же, что и при использовании with() с дополнительными ограничениями запроса.   -  person Elias Soares    schedule 16.04.2018
comment
Player::withCount('games')-›where('winner', '=', 1)-›get();   -  person Mike Foxtech    schedule 16.04.2018
comment
@EliasSoares Я только что получил пустую страницу; @MikeFoxtech Я получаю сообщение об ошибке: SQLSTATE [42S22]: Столбец не найден: 1054 Неизвестный столбец «победитель» в «предложении where» (SQL: выберите players.*, (выберите количество (*) из games внутреннего соединения game_player на games.id = game_player.game_id где players.id = game_player.player_id) как games_count из players где winner = 1)   -  person Gilko    schedule 16.04.2018
comment
Мой пример кода короткий и не включает часть ->get(). ты его включил?   -  person Elias Soares    schedule 16.04.2018
comment
@EliasSoares Вот что я использовал: $players = Player::withCount(['games' =› function($query) { $query-›where('winner', '=', 1); }]);   -  person Gilko    schedule 16.04.2018
comment
теперь я использовал -›get(); Смотрите мое обновление 2   -  person Gilko    schedule 16.04.2018


Ответы (1)


Поскольку вы определяете внешний ключ в таблице games, у вас уже есть отношение «один ко многим» между Player и Game. Попробуйте добавить следующее отношение к вашей модели Player:

// Player.php
public function won()
{
    // must specify the foreign key because it is not the usual `_id` convention.
    return $this->hasMany(Game::class, 'winner');
}

Затем получите доступ к нему на каждом игроке, например:

@foreach($players as $player)
    {{ $player->won->count() }}
@endforeach

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

public function index()
{
    /*Load the view and pass the groups*/
    return \View::make('players.index')->with('players', Player::with('won')->get());
}
person DigitalDrifter    schedule 16.04.2018
comment
Это сработало! Хороший! Спасибо, @DigitalDrifter, мне просто нужно изучить это, чтобы понять, что вы делаете. В модели игрока вы создаете функцию, в которой вы получаете игры, связанные с вашим player_id. а в представлении вы используете эту функцию со счетом? - person Gilko; 17.04.2018
comment
Да, именно. У Eloquent есть соглашения об именах, где по умолчанию используется _id в конце внешних ключей. Поскольку вы назвали свой внешний ключ winner вместо winner_id, вам нужно указать методу hasMany имя внешнего ключа. Если бы это было winner_id, вы могли бы просто сделать return $this->hasMany(Game::class); - person DigitalDrifter; 17.04.2018
comment
Хорошо :-) для чего нужен ::class? - person Gilko; 17.04.2018
comment
Однако обратите внимание, что зацикливание в представлении выполняет запросы о том, как оно написано. Лучше всего загрузить выигранные игры, как я показываю в методе контроллера, используя with. - person DigitalDrifter; 17.04.2018
comment
::class — это полное имя объекта, например App\Models\Player. - person DigitalDrifter; 17.04.2018
comment
С этим return \View::make('players.index')-›with('players', $players, Player::with('won')-›get()); Я также получаю сыгранные игры. - person Gilko; 17.04.2018