Symfony3嵌入表单验证不起作用

时间:2017-07-07 10:01:24

标签: php symfony validation

我有一个Filter和FilterCollection对象。 FilterCollection包含一组Filters,就像名称所示。 现在我需要验证所有内容,因此我创建了一个FilterType和FilterTypeCollection表单。在FilterCollectionType中我有:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('filters', CollectionType::class, array(
            'entry_type' => FilterType::class
        ));
}

在FilterCollection定义中,我有以下内容:

/**
 * @var array
 * @Assert\Valid()
 */
private $filters = [];

我创建了一个paramConverter,因此我可以将请求中的元素转换为FilterCollection。在apply方法中,我尝试使用以下方法验证所有内容:

public function apply(Request $request, ParamConverter $configuration)

    $filterCollection = new FilterCollection();

    $form = $this->formFactory->create(
        FilterTypeCollection::class,
        $filterCollection
    );

    $form->submit($request->query->all());

    if ($form->isSubmitted() && $form->isValid()) {
        $request->attributes->set($configuration->getName(), $filterCollection);

        return true;
    } else {
        throw new FormValidationException($form);
    }

}

我期待验证不仅验证FilterCollection还验证过滤器。但我在我的过滤器定义中的验证不起作用,即使我有验证失败,它仍然通过。我认为验证器没有传递Filter元素。

对可能发生的事情有任何想法?

1 个答案:

答案 0 :(得分:1)

我终于开始工作了。也许你和我犯了同样的错误,忘记在formType中的"data_class"中添加configureOptions

无论如何,这是有效的代码(在新安装的Symfony 3.3上)

DefaultController.php

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\Filter;
use AppBundle\Entity\FilterCollection;
use AppBundle\Form\FilterCollectionType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // add first filter, so we don't have to implement the collection javascript etc to test quickly
        $collection = new FilterCollection();
        $collection->filters[] = new Filter();

        $form = $this->createForm(FilterCollectionType::class, $collection);
        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            if ($form->isValid()) {
                echo "valid input"; // we don't want to see this ;)
            }
        }

        // replace this example code with whatever you need
        return $this->render('default/index.html.twig', [
            'form' => $form->createView()
        ]);
    }
}

Filter.php

<?php

namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Filter {
    /**
     * @var string
     * @Assert\NotBlank()
     * @Assert\Regex(pattern="/[0-9]+/")
     */
    public $name;
}

FilterCollection.php

<?php

namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class FilterCollection {
    /**
     * @var Filter[]
     * @Assert\Valid()
     */
    public $filters = [];
}

FilterType.php

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FilterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\Filter'
        ]);
    }
}

FilterCollectionType

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FilterCollectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('filters', CollectionType::class, [
            'entry_type' => FilterType::class,
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\FilterCollection',
        ]);
    }

    public function getName()
    {
        return 'app_bundle_filter_collection_type';
    }
}

注意:我没有像你那样制作ParamConverter,但这似乎与问题无关。您可以更改代码以轻松使用ParamConverter。