Search code examples
apisymfonyswaggeropenapiapi-platform.com

API Platform and custom POST operation with custom body


I hope I'm right to ask this. I've looked at (almost) all similar concern but I ain't satisfied yet.

I'm working on a User entity and for days (weeks actually) now i'm trying to POST a user with a custom body. Here's some part of my entity User :

/**
 * @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;

Here is the controller:

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;
    }
}

And the services.yaml (some part) file

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']

When I try this (see var_dump in controller), i get an error saying:

Cannot autowire argument $data of "App\Controller\SDK\UserChangePasswordAction()": it references class "App\Entity\User" no such service exists

I read the official doc and it seems that the _invoke method should automatically retrieve the entity. But it does not work for me.

Notice: I also defined a custom item operation "get_active_user" and it works fine.

Please I would like to understand :

  • what I did wrong,
  • how it actually works,

Thank you.

EDIT: In the collectionOperation definition, i removed the following setting which means that we manually want to handle data (User) retrieval :

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

Now, the controller returns an empty User entity, not an error. I still can't get the submitted data.


Solution

  • The edit of my question fix the concern. Actually, I just needed to remove this annotation from the POST opration definition :')

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

    Now, when I submit the data, I get them as on the following image : enter image description here

    This annotation is important when you write custom GET operation.