【问题标题】:custom validator not called when field not empty字段不为空时未调用自定义验证器
【发布时间】:2016-04-12 00:28:02
【问题描述】:

我有一个项目,其中包含 2 个实体,它们使用 FosUserBundle 链接到一个用户。这是一个实体:

AgriHealth\AhpBundle\Entity\Vet:
    type: entity
    oneToOne:
        user:
            targetEntity: User
            joinColumn:
                name: user_id
                referencedColumnName: id
    table: vet
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        firstname:
            type: string
            length: 100
        lastname:
            type: string
            length: 100
        mobile:
            type: string
            length: 15
            nullable: true
        email:
            type: string
            length: 80
        user_id:
            type: integer

为了检查电子邮件是否未被使用,我创建了一个自定义验证器:

AgriHealth\AhpBundle\Entity\Vet:
    properties:
        firstname:
            - NotBlank: ~
            - Length:
                min: 2
                max: 100
                minMessage: "Your first name must be at least {{ limit }} characters long"
                maxMessage: "Your first name cannot be longer than {{ limit }} characters long"
        lastname:
            - NotBlank: ~
            - Length:
                min: 2
                max: 100
                minMessage: "Your last name must be at least {{ limit }} characters long"
                maxMessage: "Your last name cannot be longer than {{ limit }} characters long"
        mobile:
            - Length:
                min: 2
                max: 15
                minMessage: "Your phone number must be at least {{ limit }} characters long"
                maxMessage: "Your phone number cannot be longer than {{ limit }} characters long"
        email:
            - AgriHealth\AhpBundle\Validator\Constraints\UniqueEmailAll: ~
            - Email:
                message: The email "{{ value }}" is not a valid email.
                checkMX: true
            - NotBlank: ~
        clinic:
            - NotBlank: ~

当我提交一个空表单时,会调用验证器。当我在电子邮件字段中提交任何值时,根本不会调用它。

这是来自控制器的代码:

public function createAction(Request $request)
{
    $entity = $this->getNewVet();
    $entity->setDoctrine( $this->getDoctrine() );//@todo needs to happen before handle requests NEEDS TEST
    $entity->setContainer( $this->getContainer() );
    $form = $this->createCreateForm($entity);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $em = $this->getDoctrine()->getManager();
        if ($entity->getUser()){//@todo NEEDS TEST
            if (sizeof($entity->getClinics())){
                $entity->getUser()->setRoles( array('ROLE_CLINIC_ADMIN') );
            }else{
                $entity->getUser()->setRoles( array('ROLE_VET') );
            }

        }
        $em->persist( $entity );
        $em->flush();
        return $this->redirect($this->generateUrl('vet'));
    }

    return $this->render('AgriHealthAhpBundle:Vet:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ));
}

    private function createCreateForm(Vet $entity)
    {
        $vetType = new VetType();
        $vetType
            ->setUser($this->getUser())
            ->setClinicQueryBuilder( $this->getClinicRepository()->createQueryBuilder('c') )
            ->setSecurityContext( $this->get( 'security.context' ) );
        $form = $this->createForm($vetType, $entity, array(
            'action' => $this->generateUrl('vet_create'),
            'method' => 'POST',
        ));

        $form->add('submit', 'submit', array('label' => 'Create'));

        return $form;
    }

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('firstname', 'text', array(
            'help' => '',
            'required' => true,
            'label' => 'First Name'
        ))
        ->add('lastname', 'text', array(
            'help' => '',
            'required' => true,
            'label' => 'Last Name'
        ))
        ->add('mobile', 'text', array(
            'help' => ''
        ))
        ->add('email', 'text', array(
            'help' => 'Only one address please',
            'required' => true
        ));
    if ($this->getSecurityContext()->isGranted('ROLE_CLINIC_ADMIN')) {
        $builder
            ->add('clinic', 'entity', array(
                'class' => 'AgriHealthAhpBundle:Clinic',
                'query_builder' => $this->getClinicQueryBuilder()
            ))
            ->add('clinics', 'entity', array(
                'class' => 'AgriHealthAhpBundle:Clinic',
                'query_builder' => $this->getClinicQueryBuilder(),
                'multiple' => true,
                'attr' => array(
                    'size' => 25
                ),
                'required' => false,
                'label' => 'Controls Clinics'
            ));
    }
}

/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'AgriHealth\AhpBundle\Entity\Vet'
    ));
}

/**
 * @return string
 */
public function getName()
{
    return 'agrihealth_ahpbundle_vet';
}

services.yml:

services:
    agri_health.twig.form_extension:
        class: AgriHealth\AhpBundle\Twig\FormExtension
        tags:
          - { name: twig.extension }
    agri_health.form_type_extension:
            class: AgriHealth\AhpBundle\Form\Extension\FormTypeExtension
            tags:
                - { name: form.type_extension, alias: form }
    validator.unique.unique_email_all_validator:
        class: AgriHealth\AhpBundle\Validator\Constraints\UniqueEmailAllValidator
        tags:
            - { name: validator.constraint_validator, alias: unique_email_all }

我尝试了许多其他验证器设置,但似乎都没有检查:

AgriHealth\AhpBundle\Entity\Vet:
    properties:
        email:
            - UniqueEntity:
                repositoryMethod: checkFosUserEmail

            - AgriHealth\AhpBundle\Validator\Constraints\UniqueEmailAll: ~
            - Email:
                message: The email "{{ value }}" is not a valid email.
                checkMX: true
            - NotBlank: ~
        clinic:
            - NotBlank: ~
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
              fields: email
              message: 'This port is already in use on that host.'

constraints:
    - FOS\UserBundle\Validator\Unique:
        property: usernameCanonical
        message:  'This username already exists. Please choose another one.'

AgriHealth\AhpBundle\Entity\User:
    properties:
        email_canonical:
            - UniqueEntity: ~

【问题讨论】:

  • Symfony 有一个UniqueEntity 验证器,您可以使用它来代替编写自定义验证器。见symfony.com/doc/current/reference/constraints/UniqueEntity.html
  • 我需要验证电子邮件在 2 个实体中是唯一的,而不是一个
  • 您是否按照here 的描述成功将验证器注册为服务?
  • @mattheo 我相信,当我的调试器在其中停止时,只有当电子邮件为空时。将在大约 2 小时内粘贴 services.yml
  • @jdog 你可以使用UniqueEntity 验证器并指定repository method 你可以编写一个查询来检查每2个实体

标签: forms validation symfony


【解决方案1】:

如果您不指定任何验证组,这必须为您工作:

AgriHealth\AhpBundle\Entity\Vet:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
            fields: email_canonical
            repositoryMethod: YOUR_REPOSITORY_METHOD
            errorPath: email

【讨论】:

  • 由于某种原因它没有。也许我的控制器有问题?
  • @jdog 创建表单时是否指定验证组?
  • 不,我没有指定任何内容,已将表单创建代码添加到问题中
【解决方案2】:

这实际上是由于我在实体中创建用户对象造成的。

这显然是不好的做法,因为它会破坏验证!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 2016-12-04
    • 2013-11-15
    • 2018-01-19
    • 2023-03-10
    相关资源
    最近更新 更多