简体   繁体   中英

silex form validation with dependencies

I've built a form with the silex framework that contains some checkboxes and a textfield. The user has to check at least one checkbox or write something in the textfield. Now I don't know how to validate such a dependency or better where to put the validation logic. I could add constraints to the single fields but how can I implement the dependency that either the checkboxes are validated or the textfield?

This is my validation code in the controller class.

public function validateAction(Request $request, Application $app)
{
    $form = $app['form.factory']->create(new ApplicationForm());
    $form->bind($request);
    if ($form->isValid()) {
        return $app->json(array(
            'success' => true,
        ));
    }
}

The ApplicationForm class looks like this (simplified):

class ApplicationForm extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('crafts', 'choice', array(
                'choices' => array(
                    array('drywall'     => 'Drywall'),
                    array('painter'     => 'Painter'),
                    array('plasterer'   => 'Plasterer'),
                    array('carpenter'   => 'Carpenter'),
                    array('electrician' => 'Electrician'),
                    array('plumber'     => 'Plumber'),
                    array('tiler'       => 'Tiler'),
                    array('bricklayer'  => 'Bricklayer'),
                ),
                'multiple' => true,
                'expanded' => true,
                'required' => false,
            ))
            ->add('craftsOther', 'text', array(
                'attr' => array('class' => 'textinput', 'placeholder' => 'Other', 'maxlength' => 256),
                'constraints' => array(
                    new Assert\Length(array('max' => 256, 'maxMessage' => $this->_errorMessages['crafts_other_max'])),
                ),
                'required' => false,
            ));
    }
}

Any ideas how to do this in an elegant way?

You can add constraints to the form itself, not just individual fields. You can pass an array of constraints in the options:

Here is a working example that checks both fields are not equal when submitted.

<?php

require_once __DIR__.'/../vendor/autoload.php';

use Silex\Application;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraints as Assert;

$app = new Application();

$app['debug'] = true;
$app->register(new \Silex\Provider\FormServiceProvider());
$app->register(new Silex\Provider\TranslationServiceProvider(), array('translator.domains' => array(),));
$app->register(new Silex\Provider\ValidatorServiceProvider());
$app->register(new Silex\Provider\TwigServiceProvider());

class ExampleFormType extends AbstractType
{

    public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('apple')
            ->add('banana')
            ->add('submit', SubmitType::class);
    }

    public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'constraints' => [
                new Assert\Callback(function (array $data, ExecutionContextInterface $context) {
                    if ($data['apple'] === $data['banana']) {
                        $context
                            ->buildViolation('Apple and Banana cannot be the same')
                            ->atPath('apple')
                            ->addViolation();
                    }
                }),
            ],
        ]);
    }
}

$app->match('/', function (Request $request, Application $app) {
    $form = $app['form.factory']->create(ExampleFormType::class)->handleRequest($request);
    if ($form->isValid()) {
        echo "Valid Submission";
    }

    return $app['twig']->createTemplate('{{ form(form) }}')->render([
        'form' => $form->createView(),
    ]);
})->method('GET|POST');

$app->run();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM