从数据库中获取 eloquent 个模型,包括子模型

Get eloquent model from DB including sub models

我正在学习 PHP 和 Laravel 框架,但我无法从数据库中加载一些数据。

我有 2 个模型,游戏和玩家

玩家模型(当前为空):

class Player extends Model
{
}

游戏模型:

class Game extends Model
{
    public $Players = [];

    public function __construct(array $players = [])
    {
        $this->Players = $players;
    }

    public function SaveGame()
    {
        if($this->save()) {
        Log::info("New game created with id " . $this->id);
        }
        foreach ($this->Players as $key => $player){
            if ($this->Players()->save($player)){
            Log::info("player added to game with id " . $player->id);
            }
        }
    }

    static function GetGame($gameId)
    {
        Return Game::find($gameId);
    }

    public function Players()
    {
        return $this->hasMany(Player::class );
    }
}

我有一个游戏控制器:

class GameController extends Controller
{
   public function create()
    {
        $players = [];
        for ($i = 1; $i <= 3; $i++) {
            $player = new Player();
            array_push($players,$player);
        }

        $game = new Game($players);
        $game->SaveGame();

        return $game;
    }

    public function LoadGame($id)
    {
        $game = Game::GetGame($id);
        return $game;
    }
}

如果我调用 GameController 的 create() 方法,它会在我的游戏 table 中创建一个游戏,并在玩家 table 中创建 3 个玩家,并使用相应游戏的游戏 ID,所以我认为这种关系很好。

但是如果我检查 create() 方法的响应,我只会得到这个:

{
"updated_at": "2018-03-01 15:13:37",
"created_at": "2018-03-01 15:13:37",
"id": 3952
}

还有 LoadGame() 函数 returns 只是游戏。实际上,我需要所有玩家都在里面的游戏。像这样:

{
"updated_at": "2018-03-01 15:13:37",
"created_at": "2018-03-01 15:13:37",
"id": 3952,
"players":[
       {"name":"player1"},
       {"name":"player2"},
       {"name":"player3"},
     ],
}

我做错了什么?/我怎样才能得到想要的结果?

我也不确定模型是否是执行数据库操作的正确位置,控制器是否是创建对象的地方,就像我在发布的代码中所做的那样。如果我的"code structure"不是最佳实践,也欢迎在此提出建议!

到return你可以使用的关系:

protected $appends = ['Players']

但老实说,我认为您可能想要 re-review Laravel 关系文档以了解如何正确地执行其中的某些操作。做一些重写会让你以后的生活更轻松一些。

一些注意事项:

  1. 删除 GetGame 方法,因为它是任意的。当您已经引入 class App\Game 时,您将能够 运行 find 方法。你可以去:App\Game::find($id)

  2. 删除 public $Players 以及构造,因为这些是不必要的并且会破坏关系。 Laravel 这样一来,当您创建关系后,您就可以访问它,就好像它是 class 中的一个变量一样。示例:$game->players。您可以忽略关系是作为方法创建的事实。

完成上面两件事后,你就可以修改受保护的$appends了;变量并在显示模型时查看您的关系。

太简单了!我通过简单的试验找到了解决方案,因为我在互联网上找不到解决方案。

Game 模型中,我删除了

  • constructor (不推荐在Laravel中创建自己的构造函数)
  • SaveGame() (现在将我的游戏保存在控制器中)
  • GetGame() (无用,可以在控制器中使用Game::find(x)

GameController 中,我稍微更改了 create() 函数。这是结果:

public function create()
  {
      $game = new Game();          // creates a new game
      $game->Save();               // saves the new game into the db

      for ($i = 1; $i <= 3; $i++) {
          $player = new Player();              // creates a new player
          $game->Players()->Save($player);     // stores the player to the game in the db
      }
}

我还将 GameController 中的 LoadGame() 方法更改为

public function LoadGame($id)
{
    $game = Game::find($id);        // Instead of doing this in a own method in my model 
    $game->players                  // adds the players to the game object for some reason
    return $game;                   // returns the game (as json) incl. all its players
}

这会产生一个 json 字符串,其中包含游戏变量,包括一个玩家数组及其玩家。我不明白为什么这是有效的,但确实如此。

奇怪的是,如果我将 $game->players 换成 $game->Players()$game->Players(就像模型中有很多方法一样)它不起作用。也许有人可以向我解释这是为什么? (因为我找不到任何澄清文件)