php - 特定的规范化和非规范化上下文在 Symfony 5 Api-Platform 中不起作用
问题描述
我正在学习 Piotr Jura 的这门课程。
我有一个这样的用户实体
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ApiResource(
* normalizationContext={"groups"={"GET"}},
* itemOperations={
* "GET"={
* "security"="is_granted('IS_AUTHENTICATED_FULLY')",
* "normalization_context"={
* "groups"={"GET"}
* }
* },
* "PUT"={
* "security"="is_granted('IS_AUTHENTICATED_FULLY') and object === user",
* "denormalization_context"={
* "groups"={"PUT"}
* }
* }
* },
* collectionOperations={
* "POST"={
* "denormalization_context"={
* "groups"={"POST"}
* }
* }
* }
* )
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @UniqueEntity("username")
* @UniqueEntity("email")
*/
class User implements UserInterface
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({"GET"})
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
* @Assert\Length(min=6, max=255)
* @Groups({"GET", "POST"})
*/
private $username;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
* @Assert\Regex(
* pattern="/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/",
* message="Passwords must be at least 7 characters long and contain at least one digit, one uppercaseletter, and one lowercase letter"
* )
* @Groups({"PUT", "POST"})
*/
private $password;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
* @Assert\Length(min=6, max=255)
* @Groups({"GET", "POST", "PUT"})
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
* @Assert\Email()
* @Assert\Length(min=6, max=255)
* @Groups({"POST", "PUT"})
*/
private $email;
/**
* @ORM\OneToMany(targetEntity="App\Entity\BlogPost", mappedBy="author")
* @Groups({"GET"})
*/
private $posts;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="author")
* @Groups({"GET"})
*/
private $comments;
public function __construct()
{
$this->posts = new ArrayCollection();
$this->comments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* @return Collection
*/
public function getPosts(): Collection
{
return $this->posts;
}
/**
* @return Collection
*/
public function getComments(): Collection
{
return $this->comments;
}
/**
* Returns the roles granted to the user.
*
* public function getRoles()
* {
* return ['ROLE_USER'];
* }
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* @return string[] The user roles
*/
public function getRoles()
{
return ['ROLE_USER'];
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* @return string|null The salt
*/
public function getSalt()
{
return null;
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
}
}
如您所见,在顶部@ApiResource Annotations 我试图为不同的组提供单独的规范化和非规范化上下文。
localhost:8000/api/users
当我通过使用 POST 请求和正文创建用户来测试这一点时
{
"username": "test_user1",
"password": "TestUserPassword1",
"email": "testUser1@email.com",
"name": "Test User"
}
我收到此回复
{
"@context": "/api/contexts/ConstraintViolationList",
"@type": "ConstraintViolationList",
"hydra:title": "An error occurred",
"hydra:description": "username: This value should not be blank.\npassword: This value should not be blank.\nname: This value should not be blank.\nemail: This value should not be blank.",
"violations": [
{
"propertyPath": "username",
"message": "This value should not be blank.",
"code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
},
{
"propertyPath": "password",
"message": "This value should not be blank.",
"code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
},
{
"propertyPath": "name",
"message": "This value should not be blank.",
"code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
},
{
"propertyPath": "email",
"message": "This value should not be blank.",
"code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
}
]
}
我在这里做错了什么?请帮忙!!
我在用:
- PHP 7.4.3
- Symfony 5
我的 composer.json 文件:
{
"type": "project",
"license": "proprietary",
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=7.2.5",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^2.6",
"composer/package-versions-deprecated": "1.11.99.1",
"doctrine/annotations": "^1.0",
"doctrine/doctrine-bundle": "^2.3",
"doctrine/doctrine-migrations-bundle": "^3.1",
"doctrine/orm": "^2.8",
"easycorp/easyadmin-bundle": "^3.2",
"lexik/jwt-authentication-bundle": "^2.11",
"nelmio/cors-bundle": "^2.1",
"phpdocumentor/reflection-docblock": "^5.2",
"sensio/framework-extra-bundle": "^6.1",
"symfony/asset": "5.2.*",
"symfony/console": "5.2.*",
"symfony/dotenv": "5.2.*",
"symfony/expression-language": "5.2.*",
"symfony/flex": "^1.3.1",
"symfony/framework-bundle": "5.2.*",
"symfony/property-access": "5.2.*",
"symfony/property-info": "5.2.*",
"symfony/proxy-manager-bridge": "5.2.*",
"symfony/security-bundle": "5.2.*",
"symfony/serializer": "5.2.*",
"symfony/twig-bundle": "5.2.*",
"symfony/validator": "5.2.*",
"symfony/yaml": "5.2.*"
},
"config": {
"optimize-autoloader": true,
"preferred-install": {
"*": "dist"
},
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "5.2.*"
}
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4",
"fakerphp/faker": "^1.14",
"symfony/maker-bundle": "^1.30"
}
}
解决方案
您是否确保在向POST
服务器发送请求时使用Content-Type: application/json
标头?否则 Symfony 将无法正确解码您的身体负载。
推荐阅读
- mockito - 你如何模拟 JobBuilderFactory?
- angularjs - 基于 HTTP 请求防止 AngularJS 中未经授权的 URL 更改
- c++ - SFINAE 评估中的窄化警告
- javascript - Momentjs 获取日期并设置格式
- r - 如何在 r 中由 ggplotly(来自 ggplot)生成的交互式绘图的工具提示中添加更多信息
- c++ - 在 Mac Mojave 中编译 C++ 时 C 编译器标识未知
- javascript - Javascript - Put array items, including their duplicates, into a new array
- mysql - 使用动态 SQL 存储过程,创建大量结果选项卡
- jsoup - Jsoup 用自闭文本区域弄乱 HTML
- react-native - 如何访问我的 react-native expo 应用程序的位置权限设置?