2017-07-07 22 views
1

我有一個Filter和FilterCollection對象。 FilterCollection包含一組過濾器,就像名稱所示。 現在我需要驗證一切,所以我創建了一個FilterType和FilterTypeCollection窗體。在FilterCollectionType我:Symfony3嵌入表單驗證不起作用

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那些轉換元素。在申請的方法,我嘗試驗證一切使用:

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定義中的驗證不起作用,即使我的驗證失敗了,它仍然會通過。我認爲驗證器沒有傳遞Filter元素。

關於可能發生什麼的任何想法?

+0

我不確定你的代碼有什麼問題,但也許你可以看看https://symfony.com/doc/current/reference/constraints/Collection.html - 希望它有幫助 –

+0

我試過讓它在本地工作,不能。 我確實找到了一種解決方法..您可以手動添加約束到FilterForm中的字段,例如: $ builder-> add('age',TextType :: class,['''''''''''') new Regex(['pattern'=>'/ [0-9] + /'])), ]); –

回答

1

我終於得到它的工作。也許你犯了和我一樣的錯誤,忘記在formType中的configureOptions中添加"data_class"

總之,這裏的,工程的代碼(上全新安裝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。