Partage
  • Partager sur Facebook
  • Partager sur Twitter

Api platform & SF4 - création d'une opération

Erreur lors de la création d'une opération (fonction) personnalisée

    24 octobre 2018 à 19:26:58

    Bonjour à tous,

    J'utilise actuellement Api Platform avec Symfony 4 et je souhaite créer une opération (c'est le terme employé par Api Platform) personnaliser.

    Du coup j'ai bien suivie la documentation (à cette adresse : https://api-platform.com/docs/core/operations/), mon opération est de type POST qui doit me permettre de créer une nouvelle entrée en base.

    Je souhaite créer une opération pour la classe StepApi que voici :

    <?php
    
    namespace App\Entity;
    
    use ApiPlatform\Core\Annotation\ApiResource;
    use Symfony\Component\Serializer\Annotation\Groups;
    
    use App\Controller\Api\StepSpecial;
    
    /**
     * Class Step
     * @ApiResource(itemOperations={
     *     "get",
     *     "special"={
     *          "method"="POST",
     *          "path"="/step/create",
     *          "controller"=StepSpecial::class,
     *          "defaults"={"_api_receive"=false},
     *     }
     * })
     *
     * @package App\Entity\Api\Entity
     */
    class StepApi {
    
        /**
         * @var null|string
         */
        public $title;
    
        /**
         * @var null|string
         */
        public $description;
    
        /**
         * @var int
         */
        public $latitude;
    
        /**
         * @var int
         */
        public $longitude;
    
    
        ///
        /// CONSTRUCTOR
        ///
    
        /**
         * Step constructor.
         */
        public function __construct() { }
    
    
        ///
        /// GETTER & SETTER
        ///
    
        /**
         * @return null|string
         */
        public function getTitle(): ?string {
    
            return $this->title;
        }
    
        /**
         * @param null|string $title
         */
        public function setTitle(?string $title): void {
    
            $this->title = $title;
        }
    
        /**
         * @return null|string
         */
        public function getDescription(): ?string {
    
            return $this->description;
        }
    
        /**
         * @param null|string $description
         */
        public function setDescription(?string $description): void {
    
            $this->description = $description;
        }
    
        /**
         * @return int
         */
        public function getLatitude(): int {
    
            return $this->latitude;
        }
    
        /**
         * @param int $latitude
         */
        public function setLatitude(int $latitude): void {
    
            $this->latitude = $latitude;
        }
    
        /**
         * @return int
         */
        public function getLongitude(): int {
    
            return $this->longitude;
        }
    
        /**
         * @param int $longitude
         */
        public function setLongitude(int $longitude): void {
    
            $this->longitude = $longitude;
        }
    
    }
    


    et le "controller" qui correspond à cette classe :

    <?php
    
    namespace App\Controller\Api;
    
    use App\Entity\StepApi;
    use App\Manager\StepManager;
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\Validator\Validator\ValidatorInterface;
    
    class StepSpecial {
    
        /**
         * @var \Symfony\Component\Validator\Validator\ValidatorInterface
         */
        private $validator;
    
        /**
         * @var \App\Manager\StepManager
         */
        private $manager;
    
    
        ///
        /// CONSTRUCTOR
        ///
    
        /**
         * StepSpecial constructor.
         *
         * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator
         * @param \App\Manager\StepManager                                  $stepManager
         */
        public function __construct(ValidatorInterface $validator, StepManager $stepManager) {
    
            $this->validator = $validator;
            $this->manager = $stepManager;
        }
    
    
        ///
        /// ACTIONS FUNCTIONS
        ///
    
    
        public function __invoke(StepApi $data, Request $request) {
    
            dump($data); die;
            $jsonResponse = new JsonResponse();
    
            return $jsonResponse;
        }
    
    }


    Le code fonctionne sans problème mais le problème est que le paramètre $data dans la fonction StepSpecial::__invoke() n'est pas hydraté et du coup je me retrouve avec un objet vide ... Est-ce que c'est normal ou alors il y a possibilité que le l'objet soit hydraté directement ? 

     Pour info, je fais une requête POST (avec Postman) vers l'url /api/step/create avec comme clés title, description, longitude et latitude.


    Merci pour l'aide :)

    -
    Edité par a_llow 24 octobre 2018 à 19:29:16

    • Partager sur Facebook
    • Partager sur Twitter
      23 mars 2019 à 17:44:53

      salut,

      j'ai essayé avec ton code et je ne vois pas ce qui pose soucis, je vais chercher encore et je te tiens au courant !

      j'avais en revanche moi même une question concernant apiPlatform et je ne trouve aucun forum pour le poster ! 

      - je voulais savoir s'il était possible de faire d'autres routes non gérées par apiPlatform si tout simplement nous voulions utiliser nos entity également pour notre site web dans le même projet, j'ai tenté de faire un controller normal avec l'annotation @route mais il ne la voit même pas dans le debug:router comme si apiPlatform prenait la main sur toutes les routes !

      - ensuite comment on pourrait faire une route qui renvoie des stats (le nombres d'articles, et de livres, ou même le nombre de livres par auteur ...) par exemples (des stat venant de plusieurs entity), donc il me parait abhérent de mettre cette route dans une entity en particulier, alors faut il créer une entity rien que pour cela (non liée à doctrine bien sur) ?

      si tu as des pistes je suis preneur ;-) merci d'avance

      • Partager sur Facebook
      • Partager sur Twitter
        24 mars 2019 à 20:25:21

        Bonjour 

        Je n'ai pas eu l'occasion de jouer avec l'api mais je suppose que ton controller ainsi que ta route sont bien déclarés. Ça a l'air d'être très important. 

        A tout hasard si tu supprimes ton deuxième argument dans la méthode __invoke....

        Si j'ai un peu de temps j'essaierai de répondre à la question de Rolland.steph.

        Sujet intéressant. 

        • Partager sur Facebook
        • Partager sur Twitter

        Celui qui aime à apprendre est bien près du savoir " Confucius

          25 mars 2019 à 12:37:24

          bonjour,

          En fait c'est une collection operations que tu devrais utiliser pour créer une nouvelle ressources(=POST) et non une item operation car une item operations supporte que GET, PUT, DELETE et éventuellement PATCH.

          --------------

          Une parenthèse qui n'a rien à avoir.Pour la création d'une nouvelle ressource tu n'as pas à passer StepApi en paramètre de la méthode __invoque car la ressource n'existe pas ,elle est à créer.Pour la créer, tu as 2 choix ,soit tu l'instancies et tu l'hydrates avec la request( la request est en json, donc à decoder avec json_decode) soit tu crées la ressource en passant par le serialiazer de symfony.

          <?php
          
          namespace App\Controller\Api;
          
          use App\Entity\StepApi;
          use App\Manager\StepManager;
          use Symfony\Component\HttpFoundation\JsonResponse;
          use Symfony\Component\HttpFoundation\Request;
          use Symfony\Component\HttpFoundation\Response;
          use Symfony\Component\Routing\Annotation\Route;
          use Symfony\Component\Validator\Validator\ValidatorInterface;
          use Symfony\Component\Serializer\SerializerInterface;
          
          class StepSpecial {
          
              /**
               * @var \Symfony\Component\Validator\Validator\ValidatorInterface
               */
              private $validator;
          
              /**
               * @var \App\Manager\StepManager
               */
              private $manager;
          
              /**
               * @var SerializerInterface
               */
              private $serializer; 
              ///
              /// CONSTRUCTOR
              ///
          
              /**
               * StepSpecial constructor.
               *
               * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator
               * @param \App\Manager\StepManager $stepManager
               */
              public function __construct(ValidatorInterface $validator, SerializerInterface $serializer, StepManager $stepManager) {
          
                  $this->validator = $validator;
                  $this->manager = $stepManager;
                  $this->serializer = $serializer;
              }
          
          
              ///
              /// ACTIONS FUNCTIONS
              ///
          
          
              public function __invoke(Request $request) {
          
                  /**
                   * @var StepApi
                   */
                  $stepApi = $this->serializer->deserialize($request->getContent(), StepApi::class, 'json');
                  //validation à faire ici ou via les annotations dans l'entité StepApi
                  $this->manager->persist($stepApi);
                  $this->manager->flush();
          
                  return new JsonResponse(["id" => $stepApi->getId()]);//tu peux ajouter le code de la réponse
              }
          
          }
          
          



          -
          Edité par armel.mc 25 mars 2019 à 12:37:55

          • Partager sur Facebook
          • Partager sur Twitter

          Api platform & SF4 - création d'une opération

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown