Symfony2条件表单验证

时间:2016-01-19 13:11:04

标签: validation symfony

我对仅为一个关联实体应用验证有一些困难。

所以我有两个实体NewsNewsTranslation。新闻可以用多种语言翻译。但我想仅在语言环境为en时才应用验证。

// AppBundle/Entity/News.php
class News
{
    use ORMBehaviors\Translatable\Translatable;
    use ORMBehaviors\Timestampable\Timestampable;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var int
     *
     * @ORM\Column(name="status", type="smallint")
     * @Assert\NotBlank
     */
    private $status;

    ...
}
// AppBundle/Entity/NewsTranslation.php
class NewsTranslation
{
    use ORMBehaviors\Translatable\Translation;

    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255, nullable=true)
     * @Assert\NotBlank
     * @Assert\Length(max = 255)
     */
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="text", type="string", nullable=true)
     * @Assert\NotBlank
     */
    private $text;
}
# AppBundle/Resources/config/validation.yml
AppBundle\Entity\News:
    properties:
        translations:
            - Valid: ~

我尝试将Closure用于validation_groups表单选项。但看起来Symfony对News实体进行了验证,Valid约束在NewsTranslation上应用相同的组。

我知道我可以使用Callback约束,但这意味着我自己重做NotBlankLength和其他现有约束。如果可能的话我想避免它。

修改

我正在使用Symfony 2.8。*

我尝试使用en验证组。但看起来验证是在News实体上使用validation_groups启动的。通过Valid约束,en验证组将用于验证NewsTranlation。因此,即使是en或fr翻译,在这种情况下,小组也不会改变任何内容。

我也尝试使用validation medatada@Assert\Callback或使用loadValidatorMetadata方法进入NewsTranslation实体。问题保持不变。我无法对特定的集合实体应用约束。

2 个答案:

答案 0 :(得分:2)

我终于通过创建自定义验证器找到了一种方法。 像这样我可以轻松使用核心约束。

在翻译实体中,我可以使用我的验证器:

/**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=255, nullable=true)
 * @Assert\Length(max = 255)
 * @AppAssert\ValidTranslation(locales = {"fr"}, constraints = {
 *      @Assert\NotBlank
 * })
 */
private $title;

验证员:

<?php

namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraints\Composite;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
 *
 * @author Nicolas Brousse
 */
class ValidTranslation extends Composite
{
    public $locales     = array();
    public $constraints = array();

    public function getCompositeOption()
    {
        return 'constraints';
    }

    public function getRequiredOptions()
    {
        return array('locales', 'constraints');
    }
}
<?php

namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Nicolas Brousse
 */
class ValidTranslationValidator extends ConstraintValidator
{
    /**
     * If property constraint
     * {@inheritdoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (!$constraint instanceof ValidTranslation) {
            throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\ValidTranslation');
        }

        if (false) { // @todo check by interface or trait
            throw new UnexpectedTypeException($value, 'not a translation entity');
        }

        $context = $this->context;
        $entity  = $this->context->getObject();

        if (in_array($entity->getLocale(), $constraint->locales)) {
            $context = $this->context;

            if ($context instanceof ExecutionContextInterface) {
                $validator = $context->getValidator()->inContext($context);
                $validator->validate($value, $constraint->constraints);
            } else {
                // 2.4 API
                $context->validateValue($value, $constraint->constraints);
            }
        }
    }
}

答案 1 :(得分:0)

你需要返回2个validations_groups,&#34;默认&#34;和对应于&#34; en&#34;的验证组。区域设置