【问题标题】:How to proper relate(group) Entities in Symfony and api-platform如何在 Symfony 和 api-platform 中正确关联(组)实体
【发布时间】:2021-06-09 15:49:02
【问题描述】:

我得到了错误:

Nested documents for attribute "players" are not allowed. Use IRIs instead.

所以,我知道我需要使用序列化程序创建组。

我在做什么;我使用 symfony 5、教义(SQLite)和 api-platform。

我正在制作游戏,而游戏需要玩家。所以当我在数据库中添加游戏时,我也想添加玩家。两者都有自己的实体; Game.php 和 Player.php(也在实体文件夹中)。

由于某种原因,我无法正确链接 2 个实体,我做错了什么?

我使用 API 平台来执行这个 json;

{
  "active": 0,
  "hints": 0,
  "players": [
    {
      "game": 1,
      "nickname": "string",
      "code": "string"
    }
  ],
  "price": "345",
  "gameMap": "/api/game_maps/2",
  "uidGame": "4",
  "teamName": "3",
  "secretKey": "fdgfdg",
  "startTime": "2021-03-11T11:38:45.923Z",
  "lastActionOnTime": "2021-03-11T11:38:45.923Z",
  "endTime": "2021-03-11T11:38:45.923Z",
  "penaltyTime": "g",
  "testGame": 0
}

游戏实体:

<?php

namespace App\Entity;

use App\Repository\GameRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(normalizationContext={ "groups": {"boost"} })
 * @ORM\Entity(repositoryClass=GameRepository::class)
 */
class Game
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @Groups({"boost"})
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=GameMap::class, inversedBy="games", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     * @Groups({"boost"})
     */
    private $game_map;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $uid_game;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $team_name;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $secret_key;

    /**
     * @ORM\Column(type="datetime")
     */
    private $start_time;

    /**
     * @ORM\Column(type="datetime")
     */
    private $last_action_on_time;

    /**
     * @ORM\Column(type="smallint")
     */
    private $active;

    /**
     * @ORM\Column(type="datetime")
     */
    private $end_time;

    /**
     * @ORM\Column(type="integer")
     */
    private $hints;

    /**
     * @ORM\Column(type="bigint")
     */
    private $penalty_time;

    /**
     * @ORM\Column(type="json")
     */
    private $progress = [];

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $price;

    /**
     * @ORM\Column(type="smallint")
     */
    private $test_game;

    /**
     * @ORM\OneToMany(targetEntity=Player::class, mappedBy="game", orphanRemoval=true, cascade={"persist"})
     * @Groups({"boost"})
     */
    private $players;

    /**
     * @ORM\OneToMany(targetEntity=UserGame::class, mappedBy="game", orphanRemoval=true, cascade={"persist"})
     * @Groups({"boost"})
     */
    private $userGames;
}

还有玩家实体:

<?php

namespace App\Entity;

use App\Repository\PlayerRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource()
 * @ORM\Entity(repositoryClass=PlayerRepository::class)
 */
class Player
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @Groups({"boost"})
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=Game::class, inversedBy="players")
     * @ORM\JoinColumn(nullable=false)
     * @Groups({"boost"})
     */
    private $game;

    /**
     * @ORM\Column(type="string", length=255)
     * @Groups({"boost"})
     */
    private $nickname;

    /**
     * @ORM\Column(type="string", length=255)
     * @Groups({"boost"})
     */
    private $code;
}

【问题讨论】:

标签: symfony serialization deserialization json-deserialization api-platform.com


【解决方案1】:

因此,您的情况有两个不同的问题。

  1. 使用不同的规范化和非规范化上下文。将 Game 和 Player 中所有需要的字段添加到非规范化组中:

    /**
    * @ApiResource(
    *     normalizationContext={ "groups": {"boost"} },
    *     denormalizationContext={ "groups": {"write"} }
    * )
    * @ORM\Entity()
    */
    class Game
    {
       /**
       * @ORM\Id
       * @ORM\GeneratedValue
       * @ORM\Column(type="integer")
       * @Groups({"boost"})
       */
       private $id;
    
       ...
    
    
       /**
       * @ORM\OneToMany(targetEntity=Player::class, mappedBy="game", 
         orphanRemoval=true, cascade={"persist"})
       * @Groups({"boost", "write"})
       */
       private $players;
     }
    

还有:

/**
* @ApiResource()
* @ORM\Entity()
*/
class Player
{
   /**
   * @ORM\Id
   * @ORM\GeneratedValue
   * @ORM\Column(type="integer")
   *
   * @Groups({"boost"})
   */
   private $id;

   /**
   * @ORM\ManyToOne(targetEntity=Game::class, inversedBy="players")
   * @ORM\JoinColumn(nullable=false)
   */
   private $game;

   /**
   * @ORM\Column(type="string", length=255)
   *
   * @Groups({"boost", "write"})
   */
   private $nickname;
   
   /**
   * @ORM\Column(type="string", length=255)
   *
   * @Groups({"boost", "write"})
   */
   private $code;
  1. 在您的 POST /api/games 中,您在 players 嵌套集合中的正文请求中使用 game: 1。这很糟糕,因为您实际上运行了 create game 请求。在这种情况下,如何将玩家链接到已经存在的游戏? Game 和 Player 之间的关系是 OneToMany。你明白我的意思吗?

在这些更改和 POST /api/games 正文之后

{
  "active": 0,
  "hints": 0,
  "players": [
    {
       "nickname": "string",
       "code": "string"
    }
 ],
 "price": "345",
 "uidGame": "4",
 "teamName": "3",
 "secretKey": "fdgfdg",
 "startTime": "2021-03-11T11:38:45.923Z",
 "lastActionOnTime": "2021-03-11T11:38:45.923Z",
 "endTime": "2021-03-11T11:38:45.923Z",
 "penaltyTime": "9",
 "testGame": 0
}

我在 GET /api/games 上收到了回复:

[
 {
   "id": 1,
   "uidGame": "4",
   "teamName": "3",
   "secretKey": "fdgfdg",
   "startTime": "2021-03-11T11:38:45+00:00",
   "lastActionOnTime": "2021-03-11T11:38:45+00:00",
   "active": 0,
   "endTime": "2021-03-11T11:38:45+00:00",
   "hints": 0,
   "penaltyTime": "9",
   "progress": [],
   "price": "345",
   "testGame": 0,
   "players": [
     {
       "id": 1,
       "nickname": "string",
       "code": "string"
     }
   ]
 }
]

你期待吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多