php 如果Symfony Form中的某些字段为空,则其中一个字段不应为空

t0ybt7op  于 2022-12-02  发布在  PHP
关注(0)|答案(4)|浏览(129)

在我的Symfony 2(2.4.2)应用程序中,有一个由3个字段组成的表单类型。
我希望验证是这样的:如果field Afield B为空,则field C不应为空。这意味着至少有一个字段应接收一些数据。
目前,我在控制器中检查接收到的数据。有没有更推荐的方法来做这件事?

gudnpqoy

gudnpqoy1#

还有比编写自定义验证器更简单的解决方案,其中最简单的可能是表达式约束:

class MyEntity
{
    private $fieldA;

    private $fieldB;

    /**
     * @Assert\Expression(
     *     expression="this.fieldA != '' || this.fieldB != '' || value != ''",
     *     message="Either field A or field B or field C must be set"
     * )
     */
    private $fieldC;
}

您也可以将验证方法加入至类别,并使用Callback条件约束注解它:

/**
 * @Assert\Callback
 */
public function validateFields(ExecutionContextInterface $context)
{
    if ('' === $this->fieldA && '' === $this->fieldB && '' === $this->fieldC) {
        $context->addViolation('At least one of the fields must be filled');
    }
}

方法将在类别验证期间执行。

ivqmmu1c

ivqmmu1c2#

这可能是一个Custom Validation Constraint的用例,我自己还没有用过,但基本上你创建了一个Constraint和一个Validator,然后在你的config/validation.yml中指定你的Constraint

Your\Bundle\Entity\YourEntity:
    constraints:
        - Your\BundleValidator\Constraints\YourConstraint: ~

实际的验证是由Validator完成的。您可以让Symfony将整个实体传递给validate方法,以便使用以下方法访问多个字段:

public function getTargets()
{
    return self::CLASS_CONSTRAINT;
}

您的validate

public function validate($entity, Constraint $constraint)
{
    // Do whatever validation you need
    // You can specify an error message inside your Constraint
    if (/* $entity->getFieldA(), ->getFieldB(), ->getFieldC() ... */) {
        $this->context->addViolationAt(
            'foo',
            $constraint->message,
            array(),
            null
        );
    }
}
bwitn5fc

bwitn5fc3#

可以使用组序列提供程序执行此操作,例如:

use Symfony\Component\Validator\GroupSequenceProviderInterface;

/**
 * @Assert\GroupSequenceProvider
 */
class MyObject implements GroupSequenceProviderInterface
{
    /**
     * @Assert\NotBlank(groups={"OptionA"})
     */
    private $fieldA;

    /**
     * @Assert\NotBlank(groups={"OptionA"})
     */
    private $fieldB;

    /**
     * @Assert\NotBlank(groups={"OptionB"})
     */
    private $fieldC;

    public function getGroupSequence()
    {
        $groups = array('MyObject');

        if ($this->fieldA == null && $this->fieldB == null) {
            $groups[] = 'OptionB';
        } else {
            $groups[] = 'OptionA';
        }

        return $groups;
    }
}

没有测试,但我认为它会工作

tquggr8v

tquggr8v4#

我知道这是一个老问题,但您也可以使用此包https://github.com/secit-pl/validation-bundle中的NotBlankIf验证器

<?php

use SecIT\ValidationBundle\Validator\Constraints as SecITAssert;

class Entity
{
    private ?string $fieldA = null;
    private ?string $fieldB = null;

    #[SecITAssert\NotBlankIf("!this.getFieldA() and !this.getFieldB()")]
    private ?string $fieldC = null;

    public function getFieldA(): string
    {
        return $this->fieldA;
    }

    public function getFieldB(): string
    {
        return $this->fieldB;
    }
}

相关问题