簡體   English   中英

symfony5 - 錯誤 500 頁而不是樹枝中的形式錯誤

[英]symfony5 - error 500 page instead form error in twig

我使用表單生成器設置了注冊表。

問題是 Symfony 拋出一個 InvalidArgumentException 頁面,其中包含Expected argument of type "string", "null" given at property path "user_name".消息“ Expected argument of type "string", "null" given at property path "user_name".

當然,用戶實體中的setUserNameuser_name類型定義為字符串,但我在表單構建器中添加了約束NotBlank 我預計樹枝內部會出現“此字段不能為空”之類的錯誤。

編輯:在評論 somme 屬性后,似乎在我的所有表單字段上都會發生這種行為。

為什么錯誤沒有出現在我的樹枝模板中? 我已經在 Symfony 4 中實現了這個流程,它的工作非常有魅力。

這里是建造者

<?php

namespace App\Form\Type;

use App\Entity\Department;
use App\Entity\Level;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Regex;

class InscriptionType extends AbstractType
{
    /**
     * EntityManagerInterface
     *
     * @var EntityManagerInterface
     */
    private $em;

    /**
     * Constructor
     *
     * @param EntityManagerInterface $em
     */
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    /**
     * Build the register form
     *
     * @param FormBuilderInterface $builder
     * @param array $options
     * @return void
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('user_name', TextType::class, [
                'label' => 'Nom',
                'attr' => [
                    'placeholder' => 'Doe'
                ],
                'constraints' => [
                    new Length([
                        'min' => 3,
                        'minMessage' => 'Doit comporter 2 caractères ou plus',
                    ]),
                    new Regex([
                        'pattern' => '/^[\wéèêàäâçïöôîûüù\' \-]+$/',
                        'message' => 'La chaîne comporte des caractères non autorisés',
                    ]),
                    new NotBlank()
                ]
            ])
            ->add('user_firstname', TextType::class, [
                'label' => 'Prénom',
                'attr' => [
                    'placeholder' => 'John'
                ],
                'constraints' => [
                    new Length([
                        'min' => 3,
                        'minMessage' => 'Doit comporter 2 caractères ou plus',
                    ]),
                    new Regex([
                        'pattern' => '/^[\wéèêàäâçïöôîûüù\' \-]+$/',
                        'message' => 'La chaîne comporte des caractères non autorisés',
                    ]),
                    new NotBlank()
                ],
            ])
            ->add('user_birthdate', DateType::class, [
                'label' => 'Date de naissance',
                'placeholder' => [
                    'year' => 'Année',
                    'month' => 'Mois',
                    'day' => 'Jours',
                ],
                'widget' => 'single_text',
                'input' => 'array',
                'constraints' => [
                    new NotBlank()
                ],
            ])
            ->add('email', EmailType::class, [
                'label' => 'Adresse email',
                'attr' => [
                    'placeholder' => 'john.doe@exemple.com'
                ],
                'constraints' => [
                    new NotBlank(),
                ],
            ])
            ->add('user_department', ChoiceType::class, [
                'label' => 'Département',
                'placeholder' => 'Sélectionnez un departement',
                'choices' => $this->getDepartmentList(),
                'constraints' => [
                    new NotBlank(),
                ],
            ])
            ->add('user_level', ChoiceType::class, [
                'label' => 'Niveau',
                'placeholder' => 'Sélectionnez votre niveau',
                'choices' => $this->getLevelList(),
                'constraints' => [
                    new NotBlank(),
                ],
            ])
            ->add('user_description', TextareaType::class, [
                'label' => 'Description',
                'constraints' => [
                    new Length([
                        'min' => 3,
                        'minMessage' => 'Doit comporter 2 caractères ou plus',
                    ]),
                    new NotBlank(),
                ],
            ])
            ->add('password', PasswordType::class, [
                'label' => 'Mot de passe',
                'constraints' => [
                    new Length([
                        'min' => 3,
                        'minMessage' => 'Doit comporter 2 caractères ou plus',
                    ]),
                    new NotBlank(),
                ],
            ])
            ->add('confirm_password', PasswordType::class, [
                'mapped' => false,
                'label' => 'Confirmation',
                'constraints' => [
                    new Length([
                        'min' => 3,
                        'minMessage' => 'Doit comporter 2 caractères ou plus',
                    ]),
                    new NotBlank(),
                ],
            ])
            ->add('submit', SubmitType::class, [
                'label' => 'Valider',
            ]);

        /* TO DO IMPLEMENTER CAPTCHA */
        /*
    if ($_ENV['GOOGLE_RECAPTCHA_ACTIVE'] === 'true') {
    $builder->add('CaptchaDmd', HiddenType::class,[
    'label' => 'Captcha',
    'mapped' => false, // le captcha n'est pas une propriete existante dans l'entite demandePass, on indique que on ne doit pas la mapper
    'error_bubbling' => false,
    'constraints' => [
    new NotBlank([
    'message' => $this->translator->trans('LibBlankCaptcha')
    ])
    ]
    ]);
    }
     */
    }

    /**
     * Retrieve department list
     *
     * @return void
     */
    protected function getDepartmentList()
    {
        $repo = $this->em->getRepository(Department::class);
        $departments = [];

        $departmentList = $repo->findAll();

        foreach ($departmentList as $department) {
            # $country est une instance de App\Entity\LangueInternational
            $libelle = $department->getDepartmentNom() . ' (' . $department->getDepartementCode() . ')';
            $valeur = $department->getId();

            $departments[$libelle] = $valeur;
        }

        return $departments;
    }

    /**
     * Retrieve level list
     *
     * @return void
     */
    protected function getLevelList()
    {
        $repo = $this->em->getRepository(Level::class);
        $levels = [];

        $levelList = $repo->findAll();

        foreach ($levelList as $level) {
            # $country est une instance de App\Entity\LangueInternational
            $libelle = ucfirst($level->getLevelName());
            $valeur = $level->getId();

            $levels[$libelle] = $valeur;
        }

        return $levels;
    }

}

用戶實體

<?php

namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $user_name;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $user_firstname;

    /**
     * @ORM\Column(type="date")
     */
    private $user_birthdate;

    /**
     * @ORM\Column(type="integer")
     */
    private $user_region;

    /**
     * @ORM\Column(type="integer")
     */
    private $user_department;

    /**
     * @ORM\Column(type="text")
     */
    private $user_description;

    /**
     * @ORM\Column(type="integer")
     */
    private $user_level;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->email;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function setUserName(string $user_name): self
    {
        $this->user_name = $user_name;

        return $this;
    }

    public function getUserFirstname(): ?string
    {
        return $this->user_firstname;
    }

    public function setUserFirstname(string $user_firstname): self
    {
        $this->user_firstname = $user_firstname;

        return $this;
    }

    public function getUserBirthdate(): ?\DateTimeInterface
    {
        return $this->user_birthdate;
    }

    public function setUserBirthdate(\DateTimeInterface $user_birthdate): self
    {
        $this->user_birthdate = $user_birthdate;

        return $this;
    }

    public function getUserRegion(): ?int
    {
        return $this->user_region;
    }

    public function setUserRegion(int $user_region): self
    {
        $this->user_region = $user_region;

        return $this;
    }

    public function getUserDepartment(): ?int
    {
        return $this->user_department;
    }

    public function setUserDepartment(int $user_department): self
    {
        $this->user_department = $user_department;

        return $this;
    }

    public function getUserDescription(): ?string
    {
        return $this->user_description;
    }

    public function setUserDescription(string $user_description): self
    {
        $this->user_description = $user_description;

        return $this;
    }

    public function getUserLevel(): ?int
    {
        return $this->user_level;
    }

    public function setUserLevel(int $user_level): self
    {
        $this->user_level = $user_level;

        return $this;
    }
}

模板

{{ form_start(inscriptionForm, {'attr': {'novalidate' : 'novalidate'}}) }}
      {{ form_errors(inscriptionForm) }}
      <div class="form-row">
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.user_name) }}
          {{ form_widget(inscriptionForm.user_name) }}
          {{ form_errors(inscriptionForm.user_name) }}
        </div>
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.user_firstname) }}
          {{ form_widget(inscriptionForm.user_firstname) }}
          {{ form_errors(inscriptionForm.user_firstname) }}
        </div>
      </div>
      <div class="form-row">
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.email) }}
          {{ form_widget(inscriptionForm.email) }}
          {{ form_errors(inscriptionForm.email) }}
        </div>
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.user_birthdate) }}
          {{ form_widget(inscriptionForm.user_birthdate) }}
          {{ form_errors(inscriptionForm.user_birthdate) }}
        </div>
      </div>
      <div class="form-row">
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.password) }}
          {{ form_widget(inscriptionForm.password) }}
          {{ form_errors(inscriptionForm.password) }}
        </div>
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.confirm_password) }}
          {{ form_widget(inscriptionForm.confirm_password) }}
          {{ form_errors(inscriptionForm.confirm_password) }}
        </div>
      </div>
      <div class="form-row">
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.user_level) }}
          {{ form_widget(inscriptionForm.user_level) }}
          {{ form_errors(inscriptionForm.user_level) }}
        </div>
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.user_description) }}
          {{ form_widget(inscriptionForm.user_description) }}
          {{ form_errors(inscriptionForm.user_description) }}
        </div>
      </div>
      <div class="form-row">
        <div class="form-group col-md-6">
          {{ form_label(inscriptionForm.user_department) }}
          {{ form_widget(inscriptionForm.user_department) }}
          {{ form_errors(inscriptionForm.user_department) }}
        </div>
      </div>
      <div class="form-row">
        <div class="form-group col-md-6">
          {{ form_widget(inscriptionForm.submit) }}
        </div>
      </div>
      
      {{ form_end(inscriptionForm) }}

和處理表單提交的控制器

<?php

namespace App\Controller;

use App\Entity\User;
use App\Form\Type\InscriptionType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

class InscriptionController extends AbstractController
{
    /**
     * @Route("/inscription", name="inscription")
     */
    public function inscriptionAction(Request $request)
    {
        $user = new User();
        
        // Creation du formulaire d'inscription
        $inscriptionForm = $this->createForm(InscriptionType::class, $user);

        // Si requete en POST et formulaire soumit
        if ($request->isMethod('POST')) {
          error_log('Formulaire inscription soumis');

          // On indique au formulaire de prendre en charge le contenu de la requete
          // Il va mapper les different champs soumis avec le contenu de l entite $user
          $inscriptionForm->handleRequest($request);

          if ($inscriptionForm->isSubmitted() && $inscriptionForm->isValid()) {
            error_log("Formulaire inscription ok, sauvegarde de l'inscription");
          }
        }

        // Affichage
        return $this->render('inscription.html.twig', array(
          'inscriptionForm' => $inscriptionForm->createView(),
          'errors' => (isset($errors) ? $errors : ''),
      ));
    }
}

也許您不應該使用 getUsername 返回您的電子郵件

public function getUsername(): string
{
    return (string) $this->email;
}

而你 setUserName 的 setter 設置了 $this->user_name,和 email 不一樣。

public function setUserName(string $user_name): self
{
    $this->user_name = $user_name;

    return $this;
}

函數 getUsername 在 UserInterface 中設置。

RequestHandler處理請求時,它會將空值轉換為null並且由於您的字段不可為 null,因此綁定失敗。 您可以將empty_data設置為空字符串 ( 'empty_data' => '', ) 來解決這個問題。

至於生日,你可以設置今天的日期,但這會導致數據造假。 老實說,我寧願將該字段設為可選。

查看實體,您的任何 setter 都不接受空值。 這是解決問題的另一種方法,將它們全部設置為接受null 例如,將birthday設置器更改為:

public function setUserBirthdate(?\DateTimeInterface $user_birthdate): self

然后表單將觸發驗證約束。 請注意,不使用表單的其他上下文可能會使您的實體處於無效狀態,您可能需要考慮收緊架構以避免不一致的數據,將約束移動到實體以便您可以觸發實體驗證或使用 DTO。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM