从包括子模型的DB中获取雄辩的模型

时间:2018-03-01 15:36:31

标签: php laravel-5 laravel-eloquent

我正在学习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 );
    }
}

我有一个GameController:

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()方法,它会在我的Game表中创建一个游戏,并在播放器表中创建3个玩家,并使用相应游戏的gameID,所以我认为这种关系正常。

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

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

LoadGame()函数也只返回游戏。实际上我需要内部所有玩家的游戏。像这样:

{
"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"},
     ],
}

我做错了什么?/我如何得到希望的结果?

我也不确定模型是否是进行数据库操作的正确位置,控制器是创建对象的地方,就像我在发布的代码中一样。如果我的代码结构&#34;不是最好的做法,也欢迎这方面的一些建议!

2 个答案:

答案 0 :(得分:0)

要返回您可以使用的关系:

protected $appends = ['Players']

但说实话,我想你可能想重新审视一下Laravel关系文档,看看如何正确地完成这些事情。做一些重写会让你的生活在未来变得更轻松。

给你的几个笔记:

  1. 删除GetGame方法,因为它是任意的。当您已经加入课程App\Game时,您就可以在其上运行find方法了。你可以去:App\Game::find($id)

  2. 删除公共$玩家以及构造,因为这些是不必要的并打破了关系。 Laravel使得当你创建一个关系时,你可以像访问该类中的变量一样访问它。示例:$game->players。您可以忽略关系是作为方法创建的事实。

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

答案 1 :(得分:0)

它如此简单!,我通过简单地试验arround找到了解决方案,因为我无法在互联网上找到解决方案。

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(就像模型中有很多方法一样),它就不起作用了。也许有人可以解释我为什么会这样? (因为我无法找到任何澄清文件)