Forms Symfony表单自定义约束计算失败,原因是存储库中出现意外的实体更改时间

Forms Symfony表单自定义约束计算失败,原因是存储库中出现意外的实体更改时间,forms,symfony,constraints,symfony-3.3,symfony3.x,Forms,Symfony,Constraints,Symfony 3.3,Symfony3.x,在Symfony 3.3.17应用程序中,我有一个使用自定义验证约束的带有参数的实体 class JobAd { ... /** * @ORM\Column(type="string", length=2048) * @JobAdAssert\JobAdUrlExists */ protected $url = ''; ... } JobAdUrlExists的约束如下所示 /** * @Annotation */ clas

在Symfony 3.3.17应用程序中,我有一个使用自定义验证约束的带有参数的实体

class JobAd
{
    ...

    /**
     * @ORM\Column(type="string", length=2048)
     * @JobAdAssert\JobAdUrlExists
     */
    protected $url = '';

    ...
}
JobAdUrlExists的约束如下所示

/**
 * @Annotation
 */
class JobAdUrlExists extends Constraint
{
    public $message = 'Cant use URL "{{ string }}". Its in use already.';

    public function validatedBy()
    {
        return 'job_add_url_exists.validator';
    }
}
// ...

$jobAd = $jobAdRepository->findOneBy( array( 'url' => $job_ad_url ) );
$jobAdForm = $this->createForm( JobAdType::class, $jobAd );

if('POST' === $request->getMethod()) {
    if( $request->request->has( 'job_ad' ) ) {
        $jobAdForm->handleRequest($request);
        if( $jobAdForm->isSubmitted() && $jobAdForm->isValid() ) {
            // ...
            $em->persist( $jobAd );
            $em->flush();
        }
    }
}

return $this->render( $jobAdTemplate, array(
    'form_job_ad' => $jobAdForm->createView(),
));
{{ form_start(form_job_ad) }}
{{ form_errors(form_job_ad) }}
{{ form_widget(form_job_ad.url) }}
{{ form_end(form_job_ad) }}
这是JobAdUrlExistsValidator

class JobAdUrlExistsValidator extends ConstraintValidator
{
    // ...

    public function validate( $value, Constraint $constraint )
    {
        // ...

        if( /* logic here */ ) {
            $this->context->buildViolation( $constraint->message )
                ->setParameter( '{{ string }}', $value )
                ->addViolation();
        }
    }
}
表单类型定义为

class JobAdType extends AbstractType implements ContainerAwareInterface
{
    use ContainerAwareTrait;

    public function buildForm( FormBuilderInterface $builder, array $options )
    {
        // ...

        $builder->add( 'url', TextType::class, array(
            'label' => $translator->trans( 'URL' ),
            'required' => false,
            'translation_domain' => 'messages',
            'mapped' => true,
            'data' => $url
        ));

        // add other form fields ...
    }

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

    public function getBlockPrefix()
    {
        return 'job_ad';
    }
}
我的应用程序逻辑创建了这样一个视图

/**
 * @Annotation
 */
class JobAdUrlExists extends Constraint
{
    public $message = 'Cant use URL "{{ string }}". Its in use already.';

    public function validatedBy()
    {
        return 'job_add_url_exists.validator';
    }
}
// ...

$jobAd = $jobAdRepository->findOneBy( array( 'url' => $job_ad_url ) );
$jobAdForm = $this->createForm( JobAdType::class, $jobAd );

if('POST' === $request->getMethod()) {
    if( $request->request->has( 'job_ad' ) ) {
        $jobAdForm->handleRequest($request);
        if( $jobAdForm->isSubmitted() && $jobAdForm->isValid() ) {
            // ...
            $em->persist( $jobAd );
            $em->flush();
        }
    }
}

return $this->render( $jobAdTemplate, array(
    'form_job_ad' => $jobAdForm->createView(),
));
{{ form_start(form_job_ad) }}
{{ form_errors(form_job_ad) }}
{{ form_widget(form_job_ad.url) }}
{{ form_end(form_job_ad) }}
最后,twig视图输出如下形式

/**
 * @Annotation
 */
class JobAdUrlExists extends Constraint
{
    public $message = 'Cant use URL "{{ string }}". Its in use already.';

    public function validatedBy()
    {
        return 'job_add_url_exists.validator';
    }
}
// ...

$jobAd = $jobAdRepository->findOneBy( array( 'url' => $job_ad_url ) );
$jobAdForm = $this->createForm( JobAdType::class, $jobAd );

if('POST' === $request->getMethod()) {
    if( $request->request->has( 'job_ad' ) ) {
        $jobAdForm->handleRequest($request);
        if( $jobAdForm->isSubmitted() && $jobAdForm->isValid() ) {
            // ...
            $em->persist( $jobAd );
            $em->flush();
        }
    }
}

return $this->render( $jobAdTemplate, array(
    'form_job_ad' => $jobAdForm->createView(),
));
{{ form_start(form_job_ad) }}
{{ form_errors(form_job_ad) }}
{{ form_widget(form_job_ad.url) }}
{{ form_end(form_job_ad) }}
现在-当我在表单字段中插入一个引发验证错误的URL时,会发生三件事,这让我非常困惑:

  • JobAdUrlExistsValidator中的validate方法生成冲突。但是,在评估URL是否存在时,我获取了现有的JobAd,令人惊讶的是,表示当前与表单contect呈现的JobAd的URL参数已经设置为新的(可能是错误的)URL。这是否意味着用于填写表单的基本实体在验证实际发生之前发生了更改
  • 虽然对$jobAdForm->isValid()的调用未返回true,因此既不调用$em->persist()也不调用$em->flush(),但前端中的表单不会输出任何错误,并将新URL显示为其预设值。但是,表示实体的DB条目不会更改,因此,当再次加载页面时,URL再次是旧的
  • 当输入一个在约束检查时不会失败的URL时,验证表明这也是一个错误。记住1.)中的观察结果就不足为奇了->在实际检查任何内容之前,实体的URL参数会发生更改,因此在检查新URL是否存在时,allready显然会失败,因为它确实存在-应该立即插入条目中
  • 我现在很困惑,有点绝望,不知道到哪里去寻找问题的解决方案。。。
    任何提示都是非常受欢迎的:-)

    在你的课堂作业中,你需要在你的
    $信息中转义
    (可能与你的主要问题无关,但可能有问题)@v-gael y-谢谢。正确:-)但这对实际问题没有帮助(如您所说)。