0
votes

I am writing several forms with symfony 3. My form is very like the given example in the symfony reference:

http://symfony.com/doc/current/reference/constraints/Valid.html I also have an user and an embedded address-entity. My configuration is done via yml:

PARENT User:

// src/Entity/User.php
namespace App\Entity;

class User
{
    protected $firstName;
    protected $lastName;
    protected $address;

    protected $mailOptIn;
}

CHILD Address:

// src/Entity/Address.php
namespace App\Entity;

class Address
{
    protected $street;
    protected $zipCode;
}

YML:

# config/validator/validation.yaml
App\Entity\Address:
    properties:
        street:
            - NotBlank:  { groups: [group01, group02] }
        zipCode:
            - NotBlank:  { groups: [group01, group02] }
            - Length: { min: 3, groups: [group01, group02] }

App\Entity\User:
    properties:
        firstName:
            - NotBlank: ~
            - Length:
                min: 4
        lastName:
            - NotBlank: ~
        address:
            - Valid: { groups: [group01, group02] }

BUT in some cases (depending on other fields in the parent-user-entity) it is not necessary to validate the embedded address-entity.

Now I've read a lot about callback and getter-validators, but my problem is, that I do not know, how to handle this. Another part which makes the case even more complex for me is, that i need to use validation-groups (https://symfony.com/doc/current/form/validation_groups.html ) in the address entity, due to the fact, that i validate about 20 countries, where each of them has its own validation fields.

Can anybody give me hint, how to go on? The address-validation with the groups works perfectly, i think i just need to implement some cool magic stuff in the parent-user-entity, right?

UPDATE:

I just added TWO things:

  • in class USER -> protected $mailOptIn
  • in YML-User -> address: -Valid: { groups: [group01, group02] }

The validation with the valid-key works.

What I want to implement now is, that the address-validation is only done, if the user has set mailOptIn to true, because only in that case, I need the address. Please note, that i do need groups for the address-validation, depending on what country the given address is placed.

3

3 Answers

1
votes

My solution is, to use MULTIPLE 'validation_groups' and a callback-function for them in my form-type class. I wasn't aware that it is possible to use more than one group for each form.

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults($this->addDefaults([
        'data_class' => ContactGeneral::class,
        'cascade_validation' => true,
    ]));

    $resolver->setDefaults([
        'validation_groups' => function (FormInterface $form) {
            $data = $form->getData();
            if ($data->getAddress()->isValidate()) {
                return ['ContactGeneral', 'User', 'contactUser', 'Address', $this->alsLm->getGroupName()];
            } else {
                return ['ContactGeneral', 'User', 'contactUser', 'Address'];
            }
        },
    ]);
}

see:

0
votes

The documentation might not be so clear in this case, but you have to add the Valid: ~ key on it, like:

App\Entity\User:
properties:
    firstName:
        - NotBlank: ~
        - Length:
            min: 4
    lastName:
        - NotBlank: ~
    address:
        - Valid: ~
0
votes

You can do it in your controller action :

use Symfony\Component\Form\FormError;

class MyClass {

    public function createAction(Request $request) {
        // your actual code

        // dynamic form validation
        if($form->isSubmitted()){
            $zip= $form->get('address')->get('zip')->getData();
            $street= $form->get('address')->get('street')->getData();
            if($zip == '1234' && count($street)>150){
                 $form->get('address')->get('zip')->addError(new FormError('Address cant have more than 150 char for ZIP 1234')); // add error on the ZIP field
            } else if($zip == '465' && count($street) < 3) {
                 $form->get('address')->get('street')->addError(new FormError('Address must have more than 3 char for ZIP 456')); // add error on the address field
            }
        }

        // your actual code
        if($form->isSubmitted() && $form->isValid()){

        }
    }
}