Symfony2 - 验证不适用于嵌入式表单类型

Mr *_*blo 72 php symfony

我有一个结合两个实体(用户和配置文件)的表单.

验证似乎适用于来自用户实体的表单的第一部分,并且是表单的基础.

ProfileType包含在UserType中.表单正确呈现并显示正确的信息,因此它似乎已正确连接到配置文件实体.这只是ProfileType上的验证.

任何关于为什么一个部分会验证而另一个部分不会验证的想法?

代码如下:

Validation.yml

DEMO\DemoBundle\Entity\User\Profile:
    properties:
        address1:
            - NotBlank: { groups: [profile] }
        name:
            - NotBlank: { groups: [profile] }
        companyName:
            - NotBlank: { groups: [profile] }

DEMO\DemoBundle\Entity\User\User:
    properties:
        username:
            - NotBlank:
                groups: profile
                message: Username cannot be left blank.
        email:
            - NotBlank:
                groups: profile
                message: Email cannot be left blank
            - Email:
                groups: profile
                message: The email "{{ value }}" is not a valid email.
                checkMX: true
        password:
            - MaxLength: { limit: 20, message: "Your password must not exceed {{ limit }} characters." }
            - MinLength: { limit: 4, message: "Your password must have at least {{ limit }} characters." }
            - NotBlank: ~
Run Code Online (Sandbox Code Playgroud)

UserType.php

namespace DEMO\DemoBundle\Form\Type\User;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;

use DEMO\DemoBundle\Form\Type\User\ProfileType;

class UserType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('username');
        $builder->add('email');
        $builder->add('profile', new ProfileType());
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'DEMO\DemoBundle\Entity\User\User',
            'validation_groups' => array('profile')
        );
    }

    public function getName()
    {
        return 'user';
    }
}
Run Code Online (Sandbox Code Playgroud)

ProfileType.php

namespace DEMO\DemoBundle\Form\Type\User;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormError;

class ProfileType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('name');
        $builder->add('companyName', null, array('label' => 'Company Name'));
        $builder->add('address1', null, array('label' => 'Address 1'));
        $builder->add('address2', null, array('label' => 'Address 2'));
        $builder->add('city');
        $builder->add('county');
        $builder->add('postcode');
        $builder->add('telephone');
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'DEMO\DemoBundle\Entity\User\Profile',
        );
    }

    public function getName()
    {
        return 'profile';
    }
}
Run Code Online (Sandbox Code Playgroud)

调节器

$user = $this->get('security.context')->getToken()->getUser();

        $form = $this->createForm(new UserType(), $user);

        if ($request->getMethod() == 'POST') {
            $form->bindRequest($request);

            if ($form->isValid()) {
                // Get $_POST data and submit to DB
                $em = $this->getDoctrine()->getEntityManager();
                $em->persist($user);
                $em->flush();

                // Set "success" flash notification
                $this->get('session')->setFlash('success', 'Profile saved.');
            }

        }

        return $this->render('DEMODemoBundle:User\Dashboard:profile.html.twig', array('form' => $form->createView()));
Run Code Online (Sandbox Code Playgroud)

daf*_*der 114

我花了一个时间搜索,发现它正在我的父类型的类中添加修复它'cascade_validation' => truesetDefaults()数组(如线程中已经提到的).这会导致实体约束验证在表单中显示的子类型中触发.例如

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(            
        ...
        'cascade_validation' => true,
    ));
}
Run Code Online (Sandbox Code Playgroud)

对于集合,还要确保在表单上添加集合字段'cascade_validation' => true$options数组.例如

$builder->add('children', 'collection', array(
    'type'         => new ChildType(),
    'cascade_validation' => true,
));
Run Code Online (Sandbox Code Playgroud)

这将在集合中使用的子实体中进行UniqueEntity验证.

  • 对于那些现在使用Symfony 3.0及以上版本的人:cascade_validation已被删除.请参阅下面的答案了解详情. (8认同)
  • 更简单的是,您可以在validation.yml中指定"valid"约束,以便对作为要验证的对象的属性嵌入的对象启用验证http://symfony.com/doc/current/reference/constraints/Valid.html (6认同)
  • 通过在此处筛选有关类似问题的许多其他评论: (4认同)
  • 您是如何计算出需要将cascade标志添加到集合的options数组中的?这是我的问题,但我没有在Symfony文档中遇到过它? (3认同)

cg.*_*cg. 70

使用Symfony 3.0及以上版本的注意事项:该cascade_validation选项已被删除.相反,对嵌入的表单使用以下内容:

$builder->add('embedded_data', CustomFormType::class, array(
    'constraints' => array(new Valid()),
));
Run Code Online (Sandbox Code Playgroud)

很抱歉在这个旧帖子中添加了一个稍微偏离主题的答案(Symfony 3 vs. 2),但是在这里找到这些信息可能会让我在几个小时内得救.

  • 这是Symfony 3.1.4中唯一适合我的选项.按照文档http://symfony.com/doc/current/form/embedded.html并将@Assert\Valid()Constrait添加到实体,就像它写的不起作用.在我的例子中,我使用与UserProfile(OneToOne)相关的FOSUserBundle和Custom User实体.谢谢@cg. (3认同)

小智 35

根据表单类型文档,您还可以使用Valid约束而不是cascade_validation选项.

$builder->add('children', 'collection', array(
    'type'        => new ChildType(),
    'constraints' => array(new Valid()),
));
Run Code Online (Sandbox Code Playgroud)

所有者实体的示例:

/**
 * @var Collection
 *
 * @ORM\OneToMany(targetEntity="Child", ...)
 * @Assert\Valid()
 */
private $children
Run Code Online (Sandbox Code Playgroud)