Ankündigung

Einklappen
Keine Ankündigung bisher.

Symfony 4.1 - FormType mit Bedingungen validieren.

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Symfony 4.1 - FormType mit Bedingungen validieren.

    Hallo zusammen,

    ich such mal wieder nach einem Weg und komme nicht weiter.

    Es gibt zwei FormTypes ( Person und User ) und auch die passenden Entitys dazu.
    Die Beziehung ist OneToOne.

    Ich möchte beim Validieren, aber nicht beide Formulare überprüfen, sondern PersonType immer und wenn eine Checkbox ( isActive ) true ist, auch das UserType.

    Nutze ich im PersonEntity folgendes:
    PHP-Code:
    /**
    * @Assert\Valid 
    * @ORM\OneToOne(targetEntity="App\Entity\User", mappedBy="person", cascade={"persist", "remove"}) 
    */
    private $user
    Dann wird auch immer sofort das UserType mit validiert.
    Lasse ich die Annotation @Assert\Valid weg, wird UserType nicht mit validiert.

    Soweit ok, aber wie könnte ich im Controller nachträglich den UserType Validieren?

    PHP-Code:
    if ($form->isSubmitted() && $form->isValid()) {
        
    $staffForm $form->getData();
        
    /** @var Person $personForm */
        
    $personForm $staffForm->getPerson();
        
    /** @var User $userForm */
        
    $userForm $personForm->getUser();

        if(
    $userForm->getisActive()){
            
    // Jetzt noch das UserType validieren.
            // ....
        
    }

    Bisher fällt mir nur ein, dass von Hand zu machen.
    Aber dann habe ich die Fehlermeldungen nicht direkt am Formular Element.

    Ich habe auch Validation Groups ( https://symfony.com/doc/current/vali..._provider.html ) gefunden, dass ist vielleicht nicht ganz verkehrt, aber da fehlt mir dennoch die Möglichkeit zu bestimmen, dass die zweite Gruppe geprüft werden soll, wenn ein ein bestimmter Wert gesetzt ist.
    Oder ich finde es nicht.

    Jemand eine Idee?




  • #2
    Mit den Validation Groups bist du bereits auf dem richtig weg, du kannst diese dann dynamisch anhand der übermittelten Werte setzen.
    https://symfony.com/doc/current/form...alidation.html

    Kommentar


    • #3
      obsolted ....

      Kommentar


      • #4
        Danke für die Info.
        Irgendwo habe ich noch ein Problem beim verstehen.

        Im UserType habe ich das wie folgt gebaut:

        PHP-Code:
        public function configureOptions(OptionsResolver $resolver)
            {
                
        $resolver->setDefaults([
                    
        'data_class' => User::class,
                    
        'validation_groups' => function (FormInterface $form) {
                        
        $userForm $form->getData();

                        
        // User und Person Daten Validieren?
                        
        if($userForm->getisActive()){
                            return array(
        'Person''User');
                        }
                        return array(
        'Person');
                    },
                ]);
            } 
        Laut Debugger läuft er da auch genau dann rein, wenn er es soll.


        Und in den Entitys schaut es dann so aus:
        PHP-Code:
        /**
         * @Assert\GroupSequence({"User"})
         * @ORM\Table(name="`user`")
         * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
         */
        class User implements UserInterface, \Serializable 
        PHP-Code:
        /**
         * @Assert\GroupSequence({"Person"})
         * @ORM\Entity(repositoryClass="App\Repository\PersonRepository")
         */
        class Person 
        Da ändert sich aber genau nichts.

        Kommentar


        • #5
          Einmal solltest du noch die Default Gruppe mit angegeben. Weiter solltest du dann deinem @ Valid Validator die entsprechende Gruppe dann mitgeben, so dass er nur dann aktiv wird, falls die Gruppe gesetzt ist.

          Kommentar


          • #6
            Weiter solltest du dann deinem @ Valid Validator die entsprechende Gruppe dann mitgeben, so dass er nur dann aktiv wird, falls die Gruppe gesetzt ist
            Sorry aber da werde ich gerade nicht schlau draus.

            Kommentar


            • #7
              PHP-Code:
              /**
              * @Assert\Valid(groups={"Person"})
              * @ORM\OneToOne(targetEntity="App\Entity\User", mappedBy="person", cascade={"persist", "remove"}) 
              */
              private $user
              So wird der Valid Validator nur ausgeführt, wenn die Validation Group Person gesetzt ist

              Kommentar


              • #8
                So wird der Valid Validator nur ausgeführt, wenn die Validation Group Person gesetzt ist
                Aber der soll das ja nur Validieren, wenn die Validation Group "User" gesetzt ist.
                Da ist noch ein Knoten drin irgendwo. Im Kopf und im Code!

                Mal etwas ausführlicher:

                PHP-Code:
                class UserType extends AbstractType
                {
                    public function 
                buildForm(FormBuilderInterface $builder, array $options)
                    {
                        
                $builder
                            
                ->add('loginname')
                            ->
                add('plainPassword'RepeatedType::class, array(
                                
                'type' => PasswordType::class,
                                
                'first_options'  => array('label' => 'Password'),
                                
                'second_options' => array('label' => 'Repeat Password'),
                            ))
                            ->
                add('isActive'CheckboxType::class, array(
                                
                //'required' => false,
                            
                ))

                            ->
                add('roles'EntityType::class, array(
                                
                // looks for choices from this entity
                                
                'class' => Role::class,
                                
                // uses the User.username property as the visible option string
                                
                'choice_label' => 'name',
                                
                'query_builder' => function (\App\Repository\RoleRepository $er) {
                                    return 
                $er->createQueryBuilder('r')
                                        ->
                orderBy('r.name''ASC')
                                        ->
                andWhere('r.isVisible = 1');
                                },
                                
                'multiple' => true,
                            ));
                        ;
                    }

                    public function 
                configureOptions(OptionsResolver $resolver)
                    {
                        
                $resolver->setDefaults([
                            
                'data_class' => User::class,
                            
                'validation_groups' => function (FormInterface $form) {
                                
                $userForm $form->getData();
                                
                /** @var User $userForm */
                                //$userForm = $personForm->getUser();

                                // User und Person Daten Validieren?
                                
                if($userForm->getisActive()){
                                    return array(
                'Default''Person''User'); // Das wird zurückgeliefert
                                
                }
                                return array(
                'Default''Person');
                            },
                        ]);
                    }

                PHP-Code:
                class PersonType extends AbstractType
                {
                    public function 
                buildForm(FormBuilderInterface $builder, array $options)
                    {
                        
                $builder
                            
                ->add('salutation'ChoiceType::class, array(
                                
                'choices' => array(
                                    
                Person::SALUTATION_MR => Person::SALUTATION_MR,
                                    
                Person::SALUTATION_MRS => Person::SALUTATION_MRS
                                
                )
                            ))
                            ->
                add('gender'ChoiceType::class, array(
                                
                'choices' => array(
                                    
                Person::GENDER_FEMALE => Person::GENDER_FEMALE,
                                    
                Person::GENDER_MALE => Person::GENDER_MALE,
                                )
                            ))
                            ->
                add('name')
                            ->
                add('prename')
                            ->
                add('addresses'CollectionType::class, array(
                                
                'entry_type' => AddressType::class,
                                
                'allow_add' => true,
                                
                'allow_delete' => true,
                                
                'prototype' => true,
                                
                'entry_options' => array(
                                    
                'attr' => array('class' => 'address-box')
                                ),
                            ))

                            ->
                add('contact'ContactType::class)
                            ->
                add('user'UserType::class, array(
                                
                'required' => false,
                            ))
                        ;
                    }

                    public function 
                configureOptions(OptionsResolver $resolver)
                    {
                        
                $resolver->setDefaults([
                            
                'data_class' => Person::class,
                        ]);
                    }

                Das Formular ist noch etwas Komplexer. Es gibt noch ein StaffType.

                PHP-Code:
                /**
                 * @Assert\GroupSequence({"User"})
                 * @ORM\Table(name="`user`")
                 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
                 */
                class User implements UserInterface, \Serializable
                {
                    use 
                TimestampableEntity;

                    
                /**
                     * @ORM\Id()
                     * @ORM\GeneratedValue()
                     * @ORM\Column(type="integer")
                     */
                    
                private $id;

                    
                /**
                     * @ORM\OneToOne(targetEntity="App\Entity\Person", inversedBy="user")
                     * @ORM\JoinColumn(nullable=false)
                     */
                    
                private $person;

                    
                /**
                     * @ORM\ManyToMany(targetEntity="App\Entity\Role", inversedBy="users", cascade={"persist"})
                     */
                    
                private $roles;

                    
                /**
                     * @Assert\NotBlank()
                     * @Assert\Length(min=3)
                     * @ORM\Column(type="string", length=100)
                     */
                    
                private $loginname
                PHP-Code:
                /**
                 * @Assert\GroupSequence({"Person"})
                 * @ORM\Entity(repositoryClass="App\Repository\PersonRepository")
                 */
                class Person
                {
                    use 
                TimestampableEntity;

                    const 
                SALUTATION_MR   'mr';
                    const 
                SALUTATION_MRS 'mrs';

                    const 
                GENDER_MALE   'male';
                    const 
                GENDER_FEMALE 'female';

                    
                /**
                     * @ORM\Id()
                     * @ORM\GeneratedValue()
                     * @ORM\Column(type="integer")
                     */
                    
                private $id;

                    
                /**
                     * @Assert\Valid(groups={"Person"})
                     * @ORM\OneToOne(targetEntity="App\Entity\User", mappedBy="person", cascade={"persist", "remove"})
                     */
                    
                private $user
                Vermutlich bin ich zu platt um das zu verstehen. Morgen noch mal in ruhe.

                Kommentar


                • #9
                  Also ich denke die GroupSequence kannst du komplett weg lassen. Die sind eigentlich dafür da, wenn du dein Formular in mehreren Schritten validieren willst und die Validationen aufeinander aufbauen.
                  In some cases, you want to validate your groups by steps. To do this, you can use the GroupSequence feature. In this case, an object defines a group sequence, which determines the order groups should be validated.

                  For example, suppose you have a User class and want to validate that the username and the password are different only if all other validation passes (in order to avoid multiple error messages).
                  Dann musst du dir den Ablauf deiner Form noch einmal anschauen. Es fängt bei dem Form Type an, aus welcher du deine Form gebaut hast und reicht dies dann an alle Kinder Forms weiter. Wenn ich das richtig sehe, ist das bei dir die Staff Form. Hier solltest du dann dynamisch deine Validation Groups setzen. Standardmäßig haben alle Asserts die Gruppe Default sowie den ClassName ihrer Klasse.

                  When validating just the User object, there is no difference between the Default group and the User group. But, there is a difference if User has embedded objects. For example, imagine User has an address property that contains some Address object and that you've added the Valid constraint to this property so that it's validated when you validate the Userobject.

                  If you validate User using the Default group, then any constraints on the Address class that are in the Default group will be used. But, if you validate User using the Uservalidation group, then only constraints on the Address class with the User group will be validated.

                  In other words, the Default group and the class name group (e.g. User) are identical, except when the class is embedded in another object that's actually the one being validated.

                  If you have inheritance (e.g. User extends BaseUser) and you validate with the class name of the subclass (i.e. User), then all constraints in the User and BaseUser will be validated. However, if you validate using the base class (i.e. BaseUser), then only the default constraints in the BaseUser class will be validated.

                  Kommentar


                  • #10
                    Dann musst du dir den Ablauf deiner Form noch einmal anschauen. Es fängt bei dem Form Type an, aus welcher du deine Form gebaut hast und reicht dies dann an alle Kinder Forms weiter. Wenn ich das richtig sehe, ist das bei dir die Staff Form. Hier solltest du dann dynamisch deine Validation Groups setzen.
                    Super vielen Dank!
                    Genau da dran lag es.

                    Kommentar

                    Lädt...
                    X