【问题标题】:Symfony2 conditional form validationSymfony2 条件表单验证
【发布时间】:2016-01-19 13:11:03
【问题描述】:

我在仅对一个关联实体应用验证时遇到了一些困难。

所以我有两个实体,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 翻译,该组也不会改变任何内容。

我还尝试通过@Assert\Callback 使用validation medatada 或通过将loadValidatorMetadata 方法用于NewsTranslation 实体。并且问题保持相似。我无法对特定的集合实体应用约束。

【问题讨论】:

    标签: validation symfony


    【解决方案1】:

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

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

    /**
     * @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);
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您的表单需要返回 2 个验证组,“默认”和对应于“en”语言环境的验证组

      【讨论】:

      • 是的,但是通过创建en 组验证,它将适用于所有人。我目前正在寻找使用loadValidatorMetadata 属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-04
      • 2015-11-30
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多