API 平台和自定义 POST 使用自定义主体的操作
API Platform and custom POST operation with custom body
我希望我问的是对的。我看过(几乎)所有类似的问题,但我还不满意。
我正在研究一个用户实体,几天(实际上是几周)现在我正在尝试 POST 一个具有自定义主体的用户。这是我的实体用户的一部分:
/**
* @ApiResource(
* normalizationContext={"groups"={"read"}},
* denormalizationContext={"groups"={"write"}},
* itemOperations={
* "get",
* "put",
* "delete",
* "get_active_user"={
* "method"="GET",
* "path"="/users/active/me",
* "controller"=UserReadAction::class,
* "defaults"={"_api_receive"=false},
* "swagger_context"={
* "parameters"={
*
* }
* }
* },
* },
* collectionOperations={
* "change_password"={
* "method"="POST",
* "path"="/users/active/changepassword",
* "controller"=UserChangePasswordAction::class,
* "normalization_context"={"groups"={"afup"}},
* "defaults"={"_api_receive"=false},
* "swagger_context"={
* "summary" = "Change user password",
* "parameters"={
* {
* "name" = "User",
* "in" = "body",
* "schema" = {
* "type" = "object",
* "properties" = {
* "password" = {"type"="string"},
* "nom" = {"type"="string"},
* }
* },
* "required" = "true",
* }
* },
* }
* }
* }
* )
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\Table(name="users")
*/
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @Groups({"read", "write", "afup"})
*/
private $id;
这是控制器:
namespace App\Controller\SDK;
use App\Entity\User;
use App\Service\SDK\UserService;
use Symfony\Component\Security\Core\Security;
class UserChangePasswordAction
{
public function __invoke(User $data)
{
var_dump($data);die;
}
}
和 services.yaml(部分)文件
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/*'
tags: ['controller.service_arguments']
当我尝试此操作时(请参阅控制器中的 var_dump),我收到一条错误消息:
Cannot autowire argument $data of "App\Controller\SDK\UserChangePasswordAction()": it references class "App\Entity\User" no such service exists
我看了官方文档,_invoke 方法似乎应该自动检索实体。但这对我不起作用。
注意:我还定义了一个自定义项目操作"get_active_user"并且它工作正常。
请多多谅解:
- 我做错了什么,
- 它是如何工作的,
谢谢。
编辑:
在 collectionOperation 定义中,我删除了以下设置,这意味着我们要手动处理数据(用户)检索:
- "defaults"={"_api_receive"=false},
现在,控制器 returns 一个空的用户实体,不是错误。我仍然无法获取提交的数据。
它不起作用,因为那是 CollectionOperation
。这种情况下,可以通过TokenStorageInterface
获取用户
namespace App\Controller\SDK;
use App\Entity\User;
use App\Service\SDK\UserService;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class UserChangePasswordAction
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function __invoke(Request $request) //Get request if you want o keep args empty
{
var_dump($this->tokenStorage->getToken()->getUser());die;
}
}
我的问题的编辑解决了这个问题。实际上,我只需要从 POST 操作定义中删除此注释 :')
"defaults"={"_api_receive"=false},
现在,当我提交数据时,我得到的数据如下图所示:
当您编写自定义 GET 操作时,此注释很重要。
我希望我问的是对的。我看过(几乎)所有类似的问题,但我还不满意。
我正在研究一个用户实体,几天(实际上是几周)现在我正在尝试 POST 一个具有自定义主体的用户。这是我的实体用户的一部分:
/**
* @ApiResource(
* normalizationContext={"groups"={"read"}},
* denormalizationContext={"groups"={"write"}},
* itemOperations={
* "get",
* "put",
* "delete",
* "get_active_user"={
* "method"="GET",
* "path"="/users/active/me",
* "controller"=UserReadAction::class,
* "defaults"={"_api_receive"=false},
* "swagger_context"={
* "parameters"={
*
* }
* }
* },
* },
* collectionOperations={
* "change_password"={
* "method"="POST",
* "path"="/users/active/changepassword",
* "controller"=UserChangePasswordAction::class,
* "normalization_context"={"groups"={"afup"}},
* "defaults"={"_api_receive"=false},
* "swagger_context"={
* "summary" = "Change user password",
* "parameters"={
* {
* "name" = "User",
* "in" = "body",
* "schema" = {
* "type" = "object",
* "properties" = {
* "password" = {"type"="string"},
* "nom" = {"type"="string"},
* }
* },
* "required" = "true",
* }
* },
* }
* }
* }
* )
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\Table(name="users")
*/
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @Groups({"read", "write", "afup"})
*/
private $id;
这是控制器:
namespace App\Controller\SDK;
use App\Entity\User;
use App\Service\SDK\UserService;
use Symfony\Component\Security\Core\Security;
class UserChangePasswordAction
{
public function __invoke(User $data)
{
var_dump($data);die;
}
}
和 services.yaml(部分)文件
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/*'
tags: ['controller.service_arguments']
当我尝试此操作时(请参阅控制器中的 var_dump),我收到一条错误消息:
Cannot autowire argument $data of "App\Controller\SDK\UserChangePasswordAction()": it references class "App\Entity\User" no such service exists
我看了官方文档,_invoke 方法似乎应该自动检索实体。但这对我不起作用。
注意:我还定义了一个自定义项目操作"get_active_user"并且它工作正常。
请多多谅解:
- 我做错了什么,
- 它是如何工作的,
谢谢。
编辑: 在 collectionOperation 定义中,我删除了以下设置,这意味着我们要手动处理数据(用户)检索:
- "defaults"={"_api_receive"=false},
现在,控制器 returns 一个空的用户实体,不是错误。我仍然无法获取提交的数据。
它不起作用,因为那是 CollectionOperation
。这种情况下,可以通过TokenStorageInterface
namespace App\Controller\SDK;
use App\Entity\User;
use App\Service\SDK\UserService;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class UserChangePasswordAction
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function __invoke(Request $request) //Get request if you want o keep args empty
{
var_dump($this->tokenStorage->getToken()->getUser());die;
}
}
我的问题的编辑解决了这个问题。实际上,我只需要从 POST 操作定义中删除此注释 :')
"defaults"={"_api_receive"=false},
现在,当我提交数据时,我得到的数据如下图所示:
当您编写自定义 GET 操作时,此注释很重要。