Comment filtrer/désinfecter/valider les paramètres de requête dans les opérations de l'API Rest pour Symfony 5.4
P粉617237727
P粉617237727 2023-12-18 18:58:41
0
1
564

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 :

  • Assurez-vous qu'il s'agit d'un tableau ;
  • Assurez-vous que les identifiants du tableau font réellement référence à des enregistrements de base de données ;

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 :

  • Il existe un moyen de filtrer/nettoyer les paramètres de requête dans Symfony ;
  • Il existe un moyen intégré élégant d'appliquer des contraintes de validateur personnalisées aux paramètres de requête (similaire à la validation de champ d'entité bien documentée
  • ) ;

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粉617237727
P粉617237727

répondre à tous(1)
P粉635509719

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.

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

//...
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal