Maison  >  Questions et réponses  >  le corps du texte

Comment filtrer/désinfecter/valider les paramètres de requête dans les opérations de l'API Rest pour Symfony 5.4

Je suis relativement nouveau sur Symfony 5.4 et j'ai récemment créé ma première API en utilisant cette version

Pour mon point de terminaison d'API spécifique, l'un des paramètres est un tableau d'ID.

Je dois valider le tableau via :

Je l'ai implémenté de manière simple, en vérifiant le tableau avant de conserver l'entité en utilisant le transtypage et l'existant Repository :

$parentPropertyIds = (array)$request->request->get('parent_property_ids');
if ($parentPropertyIds) {
   $parentCount = $doctrine->getRepository(Property::class)->countByIds($parentPropertyIds);

   if ($parentCount !== count($parentPropertyIds)) {
       return $this->json([
            'status'  => 'error',
            'message' => 'parent_property_id_invalid'
       ], 422);
   }

   foreach ($parentPropertyIds as $parentPropertyId) {
      $parentProperty = $doctrine->getRepository(Property::class)->find($parentPropertyId);
      $property->addParent($parentProperty);
   }
}

Cependant, cela rend l'action de mon contrôleur trop « positive pour le corps » et donne l'impression que quelque chose qui pourrait être mis en œuvre de manière plus élégante.

Je ne trouve rien dans la documentation Symfony 5.4.

Actuellement, je souhaite savoir si :

Code complet du point de terminaison :

/**
     * @Route("/property", name="property_new", methods={"POST"})
     */
    public function create(ManagerRegistry $doctrine, Request $request, ValidatorInterface $validator): Response
    {
        $entityManager = $doctrine->getManager();

        $property = new Property();
        $property->setName($request->request->get('name'));
        $property->setCanBeShared((bool)$request->request->get('can_be_shared'));

        $parentPropertyIds = (array)$request->request->get('parent_property_ids');
        if ($parentPropertyIds) {
            $parentCount = $doctrine
                ->getRepository(Property::class)
                ->countByIds($parentPropertyIds);

            if ($parentCount !== count($parentPropertyIds)) {
                return $this->json([
                    'status'  => 'error',
                    'message' => 'parent_property_id_invalid'
                ], 422);
            }

            foreach ($parentPropertyIds as $parentPropertyId) {
                $parentProperty = $doctrine->getRepository(Property::class)->find($parentPropertyId);
                $property->addParent($parentProperty);
            }
        }

        $errors = $validator->validate($property);

        if (count($errors) > 0) {
            $messages = [];
            foreach ($errors as $violation) {
                $messages[$violation->getPropertyPath()][] = $violation->getMessage();
            }
            return $this->json([
                'status'   => 'error',
                'messages' => $messages
            ], 422);
        }

        $entityManager->persist($property);
        $entityManager->flush();

        return $this->json([
            'status' => 'ok',
            'id'     => $property->getId()
        ]);
    }

P粉617237727P粉617237727280 Il y a quelques jours483

répondre à tous(1)je répondrai

  • P粉635509719

    P粉6355097192023-12-19 16:22:56

    Vous pouvez combiner des objets de transfert de données (DTO) avec des services d'Authentification. Il existe de nombreuses contraintes prédéfinies, ou vous pouvez créer une contrainte personnalisée. < /p>

    Par exemple, comment utiliser des contraintes simples comme annotations :

    class PropertyDTO {
      /**
       * @Assert\NotBlank
       */
      public string $name = "";
      public bool $shared = false;
    }

    Ensuite, attribuez les données au DTO :

    $propertyData = new PropertyDTO();
    $propertyData->name = $request->request->get('name');
    ...

    Dans certains cas, il est préférable de définir le constructeur dans le DTO puis de demander à et de le transmettre immédiatement au DTO :

    $data = $request->getContent(); // or $request->getArray(); depends on your content type
    $propertyData = new PropertyDTO($data);

    Ensuite, vérifiez-le :

    $errors = $validator->validate($propertyData);
    
    if (count($errors) > 0) {
        /*
         * Uses a __toString method on the $errors variable which is a
         * ConstraintViolationList object. This gives us a nice string
         * for debugging.
         */
        $errorsString = (string) $errors;
    
        return $this->json([
                    'status'  => 'error',
                    'message' => 'parent_property_id_invalid'
                ], 422);
    }
    
    //...

    répondre
    0
  • Annulerrépondre