代码之家  ›  专栏  ›  技术社区  ›  Element Zero

Symfony 4处理空DateType表单字段

  •  7
  • Element Zero  · 技术社区  · 7 年前

    ->add('DateOfBirth', DateType::class, array(
        'required' => false,
        'widget' => 'single_text',
        'empty_data' =
    ))
    

    但是,该字段是可选的,可以为表单填写。当我提交该字段值为空的表单时,我收到错误:

    在线路上出错

    $form->handleRequest($request);
    

    this 页面并尝试了各种方法(即更改输入类型),但似乎没有任何方法可以解决此问题。

    提前谢谢!

    <?php
    
    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use NoProtocol\Encryption\MySQL\AES\Crypter;
    
    /**
     * @ORM\Entity(repositoryClass="App\Repository\PatientsRepository")
     * @ORM\Table(name="Patients")
     */
    class PatientSearch
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
    
        /**
         * @ORM\Column(type="integer")
         */
        private $PatientId;
    
        /**
         * @ORM\Column(type="string", length=100, nullable=true)
         */
        private $Address1;
    
        /**
         * @ORM\Column(type="string", length=100, nullable=true)
         */
        private $Address2;
    
        /**
         * @ORM\Column(type="string", length=50, nullable=true)
         */
        private $City;
    
        /**
         * @ORM\Column(type="string", length=2, nullable=true)
         */
        private $State;
    
        /**
         * @ORM\Column(type="date", nullable=true)
         */
        private $DateOfBirth;
    
        /**
         * @ORM\Column(type="string", length=50)
         */
        private $LastName;
    
        /**
         * @ORM\Column(type="string", length=50)
         */
        private $FirstName;
    
        public function getId(): ?int
        {
            return $this->id;
        }
    
        public function getPatientId(): ?int
        {
            return $this->PatientId;
        }
    
        public function setPatientId(int $PatientId): self
        {
            $this->PatientId = $PatientId;
    
            return $this;
        }
    
        public function getAddress1(): ?string
        {
            return $this->Address1;
        }
    
        public function setAddress1(string $Address1): self
        {
            $this->Address1 = $Address1;
    
            return $this;
        }
    
        public function getAddress2(): ?string
        {
            return $this->Address2;
        }
    
        public function setAddress2(string $Address2): self
        {
            $this->Address2 = $Address2;
    
            return $this;
        }
    
        public function getCity(): ?string
        {
            return $this->City;
        }
    
        public function setCity(string $City): self
        {
            $this->City = $City;
    
            return $this;
        }
    
        public function getState(): ?string
        {
            return $this->State;
        }
    
        public function setState(string $State): self
        {
            $this->State = $State;
    
            return $this;
        }
    
        public function getDateOfBirth(): ?\DateTimeInterface
        {
            return $this->DateOfBirth;
        }
    
        public function setDateOfBirth(\DateTimeInterface $DateOfBirth): self
        {
            $this->DateOfBirth = $DateOfBirth;
    
            return $this;
        }
    
        public function getLastName(): ?string
        {
            return $this->LastName;
        }
    
        public function setLastName(string $LastName): self
        {
            $this->LastName = $LastName;
    
            return $this;
        }
    
        public function getFirstName(): ?string
        {
            return $this->FirstName;
        }
    
        public function setFirstName(string $FirstName): self
        {
            $this->FirstName = $FirstName;
    
            return $this;
        }
    }
    

    类型:

    <?php
    
    namespace App\Form;
    
    use App\Entity\PatientSearch;
    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use Symfony\Component\Form\Extension\Core\Type\DateType;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    class PatientSearchType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('FirstName', TextType::class, array('required' => false))
                ->add('LastName', TextType::class, array('required' => false))
                ->add('DateOfBirth', DateType::class, array(
                    'required' => false,
                    'widget' => 'single_text',
                    'empty_data'  => '',
                    ))
            ;
        }
    
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => PatientSearch::class,
            ]);
        }
    }
    

    控制器:

    <?php
    
    namespace App\Controller;
    
    use App\Form\PatientSearchType;
    use App\Entity\PatientSearch;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\HttpFoundation\Request;
    
    class PatientSearchController extends AbstractController
    {
        /**
         * @Route("/patient/search", name="patient_search")
         */
        public function index(Request $request)
        {
            $form = $this->createForm(PatientSearchType::class);
    
            $form->handleRequest($request);
    
            dump($form);
            dump($form->isValid());
    
            $search = null;
            if ($form->isSubmitted() && $form->isValid()) {
                $searchFormData = $form->getData();
                dump($searchFormData);
                $search = $this->getDoctrine()
                    ->getRepository(PatientSearch::class)
                    ->findBy(array(
                        'LastName' => $searchFormData->getLastName(),
                        'FirstName' => $searchFormData->getFirstName(),
                        'DateOfBirth' => $searchFormData->getDateOfBirth(),
                        ));
    
            }
    
            return $this->render('patient_search/index.html.twig', [
                'search_form' => $form->createView(),
                'search' => $search
            ]);
        }
    }
    

    FormErrorIterator {#542 ▼
      -form: Form {#507 ▼
        -config: FormBuilder {#508 ▶}
        -parent: null
        -children: OrderedHashMap {#509 ▼
          -elements: array:3 [▼
            "FirstName" => Form {#510 ▶}
            "LastName" => Form {#513 ▶}
            "DateOfBirth" => Form {#516 ▼
              -config: FormBuilder {#517 ▶}
              -parent: Form {#507}
              -children: OrderedHashMap {#518 ▶}
              -errors: array:1 [▼
                0 => FormError {#825 ▼
                  #messageTemplate: "This value is not valid."
                  #messageParameters: array:1 [▼
                    "{{ value }}" => "1/1/2000"
                  ]
                  #messagePluralization: null
                  -message: "This value is not valid."
                  -cause: ConstraintViolation {#794 ▼
                    -message: "This value is not valid."
                    -messageTemplate: "This value is not valid."
                    -parameters: array:1 [▶]
                    -plural: null
                    -root: Form {#507}
                    -propertyPath: "children[DateOfBirth]"
                    -invalidValue: "1/1/2000"
                    -constraint: Form {#532 ▶}
                    -code: "1dafa156-89e1-4736-b832-419c2e501fca"
                    -cause: TransformationFailedException {#520 ▶}
                  }
                  -origin: Form {#516}
                }
              ]
              -submitted: true
              -clickedButton: null
              -modelData: null
              -normData: null
              -viewData: "1/1/2000"
              -extraData: []
              -transformationFailure: TransformationFailedException {#520 ▼
                #message: "Unable to reverse value for property path "DateOfBirth": Date parsing failed: U_PARSE_ERROR"
                #code: 0
                #file: "/mnt/c/Users/ElementZero/source/php/phleb-manager/vendor/symfony/form/Form.php"
                #line: 1137
                -previous: TransformationFailedException {#523 ▶}
                trace: {▶}
              }
              -defaultDataSet: true
              -lockSetData: false
            }
          ]
          -orderedKeys: array:3 [▶]
          -managedCursors: []
        }
        -errors: []
        -submitted: true
        -clickedButton: null
        -modelData: PatientSearch {#501 ▶}
        -normData: PatientSearch {#501 ▶}
        -viewData: PatientSearch {#501 ▶}
        -extraData: []
        -transformationFailure: null
        -defaultDataSet: true
        -lockSetData: false
      }
      -errors: []
    }
    
    2 回复  |  直到 7 年前
        1
  •  6
  •   Fabien Papet    7 年前

    empty_data 选择这样做。

    $builder
         ->add('someDate', \Symfony\Component\Form\Extension\Core\Type\DateType::class, [
            'widget' => 'single_text',
            'required' => false,
            'empty_data' => '',
         ])
    ;
    
        2
  •  5
  •   jdarlan Element Zero    7 年前

    我只是用了一个 TextType 这样做,因为它更容易,似乎没有一个解决方案与使用 DateType . 事实上,这似乎是一个正在讨论的symfonygithub问题(ticket) here )作为 DateTimeType 似乎不能正常工作 empty_data 属性。

    date 类型,但当您设置它时,类型是 string datetime 数据类型。

    ->add('DateOfBirth', TextType::class, array(
        'required' => false,
        'empty_data' => null,
        'attr' => array(
            'placeholder' => 'mm/dd/yyyy'
        )))
    

    细枝锉

    {{ form_widget(search_form.DateOfBirth) }}
    

    实体文件

    /**
     * @ORM\Column(type="date", nullable=true)
     */
    private $DateOfBirth;
    
    ...
    
    public function getDateOfBirth(): ?\DateTimeInterface
    {
        return $this->DateOfBirth;
    }
    
    public function setDateOfBirth(string $DateOfBirth): self
    {
        try {
    
            $this->DateOfBirth = new \DateTime($DateOfBirth);
        }
        catch(\Exception $e) {
           //Do Nothing
        }
    
        return $this;
    }
    
        3
  •  5
  •   Artem Akash Sawant    6 年前

    你应该允许放 正确版本:

    public function setDateOfBirth(?\DateTimeInterface $DateOfBirth): self
    {
        $this->DateOfBirth = $DateOfBirth;
    
        return $this;
    }
    

    因为实体是在验证之前由setters从请求中填充值的

        4
  •  4
  •   ttskch    6 年前

    by_reference DateType、DateTimeType和TimeType中的选项 is false .

    here $this->propertyAccessor->setValue($data, $propertyPath, $propertyValue); 被称为 here {An instance of PatientSearch}->setDateOfBirth(null)

    setDateOfBirth(\DateTimeInterface $DateOfBirth) 不可为null。所以你得到了那个错误。

    您可以通过如下方式使参数可为null来防止错误:

    public function setDateOfBirth(?\DateTimeInterface $DateOfBirth): self
    {
        $this->DateOfBirth = $DateOfBirth;
    
        return $this;
    }
    

    或者转身 参照 true 这样地:

    ->add('DateOfBirth', DateType::class, array(
        'required' => false,
        'widget' => 'single_text',
        'by_reference' => true,
    ))
    
        5
  •  3
  •   Mariano Seif    6 年前

    我也犯了同样的错误。我的解决方案是在表单中创建一个新的Datetype字段,使用另一个名称,但使用选项“mapped”=>false。这样symfony就不会将此字段与任何实体属性进行比较。

    ->add('formDateOfBirth', DateType::class, [
                    'label' => 'Date of Birth',
                    'mapped' => false,
                    'widget'=>'single_text',
                    'input' => 'datetime',
                    'html5' => 'false',
                    'constraints' => [new NotBlank(['message'=>'Pick a date!']),
                        new NotNull(['message'=>'Pick a date!'])],
                ])
    

    if ($form->isSubmitted() && $form->isValid()) {
                $searchFormData = $form->getData();
                $searchFormData->setDateOfBirth = $form['formDateOfBirth']->getData()
    
    推荐文章