【问题标题】:API Platform and custom POST operation with custom bodyAPI 平台和自定义 POST 操作与自定义正文
【发布时间】:2019-02-19 21:22:18
【问题描述】:

我希望我问这个问题是对的。我看过(几乎)所有类似的担忧,但我还不满意。

我正在处理用户实体,并且几天(实际上是几周)现在我正在尝试使用自定义正文发布用户。这是我的实体用户的一部分:

/**
 * @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),我收到一条错误消息:

无法自动装配“App\Controller\SDK\UserChangePasswordAction()”的参数 $data:它引用了类“App\Entity\User”,不存在此类服务

我阅读了官方文档,似乎 _invoke 方法应该自动检索实体。但这对我不起作用。

注意:我还定义了一个自定义项操作“get_active_user”,它工作正常。

我想了解一下:

  • 我做错了什么,
  • 它实际上是如何工作的,

谢谢。

编辑: 在 collectionOperation 定义中,我删除了以下设置,这意味着我们要手动处理数据(用户)检索:

  • "defaults"={"_api_receive"=false},

现在,控制器返回一个空的用户实体,而不是错误。我仍然无法获取提交的数据。

【问题讨论】:

    标签: api symfony swagger openapi api-platform.com


    【解决方案1】:

    我的问题的编辑解决了这个问题。实际上,我只需要从 POST 操作定义中删除此注释 :')

    "defaults"={"_api_receive"=false},

    现在,当我提交数据时,我得到的数据如下图所示:

    在编写自定义 GET 操作时,此注解很重要。

    【讨论】:

      【解决方案2】:

      它不起作用,因为那是 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;
          }
      }
      

      【讨论】:

      • 谢谢。我试过了,它没有从 $tokenStorage var 中找到 getUser() 方法(而且似乎接口没有这个方法)。此外,当我 var_dump 请求参数时,我没有发送的正文。这是正常的吗?再次感谢您。
      • 哦,抱歉……它是 getToken()->getUser()。无论如何...为什么不在项目操作中使用自定义操作?
      • 我试过了,它只显示记录的使用情况,而不是发送的数据。另一方面,POST 是一个集合操作(​​根据文档:api-platform.com/docs/core/operations)“集合操作作用于资源集合。默认情况下实现了两条路由:POST 和 GET”无论如何,我把它放在你的项目操作和它的作用相同。
      • 是的,对不起,我的意思是...如果您要修改已经存在的实体的属性(密码),为什么不使用 PUT?
      • 我注意到它并没有改变任何东西,只是我需要提供 id。对我来说最重要的是能够获取通过正文发送的数据,它可以是 POST 或 PUT,您可能需要有一天使用某些字段。所以 POST 似乎是最简单的尝试方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多