Symfony + API 平台:当 POST 数据具有意外(例如输入错误)的属性时,有没有办法抛出错误?
Symfony + API Platform: Is there a way to throw an error when POST data has unexpected (eg. mistyped) properties?
假设我有一个名为“Foo”的 API 资源和 属性 “bar”,我使 POST 操作可用于创建一个新实例:
POST /api/foo
{
"bar": "whatever"
}
如果我的 API 用户错误输入 属性,如下所示:
POST /api/foo
{
"bat": "whatever"
}
没有错误。
我可以在 属性“bar”上添加 NotNull 约束,这样如果“bar”不包含在内,就会抛出错误,但是如果“bar”可以为 null 怎么办?现在的结果是“bar”变为 NULL,这不是最终用户所期望的。
或者,如果添加任何其他属性,则不会引发错误或警告,例如,如果“发布”不是 属性 但提交了以下内容:
POST /api/foo
{
"bar": "whatever",
"publish": true
}
没有关于意外“发布”的错误或警告属性。最终用户可能希望此 属性 可用,可能是因为它存在于其他资源上,但响应中没有错误。显然最终用户应该阅读文档,但我更愿意直接在响应中提供反馈以确保 100% 合规。
总结:
如果我的 API 的用户添加了错误的属性,或者不小心输入了错误的 属性 名称,我该如何检测并抛出错误?
您可以将@Groups 注释与denormalization_context 一起使用。因此,您声明了被授予更新的属性。并使用强类型提示
<?php
declare(strict_types=1);
namespace AppBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* Class Foo
* @package AppBundle\Entity
* @ORM\Entity()
* @ORM\Table()
* @ApiResource(
* attributes={
* "normalization_context"={"groups"={"get"}},
* "denormalization_context"={"groups"={"put, "post"}}
* },
* itemOperations={},
* collectionOperations={"post"}
* )
*/
class Foo
{
/**
* @var string
* @ORM\Column(name="bar", type="string", nullable=false)
* @Groups({"get", "post"})
*/
private string $bar;
/**
* @var string
* @ORM\Column(name="bar", type="string", nullable=false)
* @Groups({"get"})
*/
private string $bat;
/**
* @var bool
* @ORM\Column(name="public", type="boolean", nullable=false)
* @Groups({"get", "post"})
*/
private bool $public;
/**
* @return string
*/
public function getBar(): string
{
return $this->bar;
}
/**
* @param string $bar
*
* @return Foo
*/
public function setBar(string $bar): Foo
{
$this->bar = $bar;
return $this;
}
/**
* @return string
*/
public function getBat(): string
{
return $this->bat;
}
/**
* @param string $bat
*
* @return Foo
*/
public function setBat(string $bat): Foo
{
$this->bat = $bat;
return $this;
}
/**
* @return bool
*/
public function isPublic(): bool
{
return $this->public;
}
/**
* @param bool $public
*
* @return Foo
*/
public function setPublic(bool $public): Foo
{
$this->public = $public;
return $this;
}
}
您可以看到 属性 $bat 没有组注释“post”:因此您的 POST 请求中未授权此字段。您也可以添加一些约束:例如:
use Symfony\Component\Validator\Constraint as Assert;
//...
/**
* @var string
* @ORM\Column(name="bar", type="string", nullable=false)
* @Groups({"get", "post"})
* @Assert\NotBlank(message="property bar is mandatory")
*/
private string $bar;
希望对您有所帮助。
我意识到这与反规范化步骤有关,最终发现:
/**
* @ApiResource(
* denormalizationContext={"allow_extra_attributes"=false}
* )
*/
参考:https://github.com/api-platform/core/issues/1217#issuecomment-488662805
假设我有一个名为“Foo”的 API 资源和 属性 “bar”,我使 POST 操作可用于创建一个新实例:
POST /api/foo
{
"bar": "whatever"
}
如果我的 API 用户错误输入 属性,如下所示:
POST /api/foo
{
"bat": "whatever"
}
没有错误。
我可以在 属性“bar”上添加 NotNull 约束,这样如果“bar”不包含在内,就会抛出错误,但是如果“bar”可以为 null 怎么办?现在的结果是“bar”变为 NULL,这不是最终用户所期望的。
或者,如果添加任何其他属性,则不会引发错误或警告,例如,如果“发布”不是 属性 但提交了以下内容:
POST /api/foo
{
"bar": "whatever",
"publish": true
}
没有关于意外“发布”的错误或警告属性。最终用户可能希望此 属性 可用,可能是因为它存在于其他资源上,但响应中没有错误。显然最终用户应该阅读文档,但我更愿意直接在响应中提供反馈以确保 100% 合规。
总结: 如果我的 API 的用户添加了错误的属性,或者不小心输入了错误的 属性 名称,我该如何检测并抛出错误?
您可以将@Groups 注释与denormalization_context 一起使用。因此,您声明了被授予更新的属性。并使用强类型提示
<?php
declare(strict_types=1);
namespace AppBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* Class Foo
* @package AppBundle\Entity
* @ORM\Entity()
* @ORM\Table()
* @ApiResource(
* attributes={
* "normalization_context"={"groups"={"get"}},
* "denormalization_context"={"groups"={"put, "post"}}
* },
* itemOperations={},
* collectionOperations={"post"}
* )
*/
class Foo
{
/**
* @var string
* @ORM\Column(name="bar", type="string", nullable=false)
* @Groups({"get", "post"})
*/
private string $bar;
/**
* @var string
* @ORM\Column(name="bar", type="string", nullable=false)
* @Groups({"get"})
*/
private string $bat;
/**
* @var bool
* @ORM\Column(name="public", type="boolean", nullable=false)
* @Groups({"get", "post"})
*/
private bool $public;
/**
* @return string
*/
public function getBar(): string
{
return $this->bar;
}
/**
* @param string $bar
*
* @return Foo
*/
public function setBar(string $bar): Foo
{
$this->bar = $bar;
return $this;
}
/**
* @return string
*/
public function getBat(): string
{
return $this->bat;
}
/**
* @param string $bat
*
* @return Foo
*/
public function setBat(string $bat): Foo
{
$this->bat = $bat;
return $this;
}
/**
* @return bool
*/
public function isPublic(): bool
{
return $this->public;
}
/**
* @param bool $public
*
* @return Foo
*/
public function setPublic(bool $public): Foo
{
$this->public = $public;
return $this;
}
}
您可以看到 属性 $bat 没有组注释“post”:因此您的 POST 请求中未授权此字段。您也可以添加一些约束:例如:
use Symfony\Component\Validator\Constraint as Assert;
//...
/**
* @var string
* @ORM\Column(name="bar", type="string", nullable=false)
* @Groups({"get", "post"})
* @Assert\NotBlank(message="property bar is mandatory")
*/
private string $bar;
希望对您有所帮助。
我意识到这与反规范化步骤有关,最终发现:
/**
* @ApiResource(
* denormalizationContext={"allow_extra_attributes"=false}
* )
*/
参考:https://github.com/api-platform/core/issues/1217#issuecomment-488662805