3

到目前为止,我们一直在与 Symfony、Doctrine 和 Serializer 深度作斗争。

我希望能够为 Symfony 提供仅一级深度的 JSON REST API,允许我直接从视图管理我的“外键”和关系逻辑。

GET /people/1

{
  id:1,
  name:"theonewhoknocks",
  friends: [3, 12, 25]
}

使用 FosRESTBundle,我们一直在努力取得成功。(我们已经看到模型的“深度”注释和“组”视图,但这些都不符合我们的需要)。

问题很简单,在我们为未来的 API 做出选择之前,我们必须知道:

api-platform是否能够提供非常简单的一层(带有明显的外键)REST API?

4

3 回答 3

3

API 平台可以使用Serializer Symfony 包及其注释集来处理。

为了定义操作将返回什么,我们使用normalizationContext定义属性组以包含在 api 操作的结果中。然后包含的属性将此组名称链接到@Groups序列化器注释

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
 * @ORM\Entity()
 * @ApiResource(normalizationContext={"groups"={"read"}}
 */
class Book {
    /**
     * @ORM\Column()
     * @Groups({"read"})
     */
    private $title;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="books")
     * @Groups({"read"})
     */
    private $author;

    /**
     * Will not be included in result
     */
    private $secret_comment;

}

如果关系列在$author此处的组中,则在子类中的组中定义的属性将包含在结果中

/**
 * @ORM\Entity()
 * @ApiResource(normalizationContext={"groups"={"read"}})
 */
class User {
    /**
     * @ORM\Column()
     * @Groups({"read"})
     */
    private $username;
}

为了避免循环递归,您可以使用注释指定子关系连接的最大深度,@MaxDepth(n)其中 n 是最大深度(在您的情况下为 1)。此注释必须在注释enable_max_depth的序列化程序上下文中使用属性启用@ApiResource

/**
 * @ApiPlatform(normalizationContext={"groups"={"read"}, "enable_max_depth"=true})
 */
class Book {
    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="books")
     * @Groups({"read"})
     * @MaxDepth(1)
     */
    private $author;
}

请注意,在这种情况下,API 平台是现有捆绑包和功能的集合。有关详细信息,请参阅主要包(此处为 Symfony 序列化器包)

于 2018-07-11T08:45:07.147 回答
3

请注意,MaxDepthsymfony 序列化程序上的 可能无法按预期运行,请参阅https://github.com/symfony/symfony/issues/33466

注释基本上说“从这里开始,将同一类的最大 N 个实例渲染到图中”

所以给定一个伪结构

Class A:
    @MaxDepth(1)
    Class B:
        Class C:
            Class D:

会渲染整个事情A.B.C.D,而

Class A:
    @MaxDepth(1)
    Class B:
        Class B:
            Class B:

只会渲染A.B.B

这与 JMS 序列化程序所做的完全不同,这MaxDepth实际上意味着“从这里开始,最多 N 步进入关系图”。

不好的是 api-platform 不支持 JMS 序列化程序:https ://github.com/api-platform/api-platform/issues/753

所以你的问题的答案,atm,是:不。:/

于 2020-08-03T14:47:25.870 回答
0

正如@leberknecht 指出的那样,您可能无法使用MaxDepth.

这个脚本:

#[ApiResource(
    normalizationContext: ['enable_max_depth'=>true],
)]
class User
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[ORM\Column(type: 'string', length: 180)]
    private ?string $someProperty = null;

    #[ORM\ManyToOne(targetEntity: UserClass::class)]
    #[SymfonyMaxDepth(1)]
    private ?User $createdBy = null;
}

将返回:

{
    "id": 123,
    "someProperty": "objectProperty",
    "createdBy": {
        "id": 20,
        "someProperty": "parentProperty",
        "createdBy": "users/5"
    }
}

这个脚本:

#[ApiResource]
class User
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[ORM\Column(type: 'string', length: 180)]
    private ?string $someProperty = null;

    #[ORM\ManyToOne(targetEntity: UserClass::class)]
    #[ApiProperty(readableLink: false, writableLink: false)]
    private ?User $createdBy = null;
}

将返回

{
    "id": 123,
    "someProperty": "objectProperty",
    "createdBy": "users/20"
}
于 2022-01-24T17:13:38.973 回答