php 验证相互依赖的Symfony约束:为自定义验证检索已验证的上下文

sgtfey8w  于 2023-05-27  发布在  PHP
关注(0)|答案(1)|浏览(332)

我有一个从全局请求创建的DTO对象。在这个DTO中,我有一些我正在使用的Symfony约束验证器,我有一个自定义验证器来检查数据库中是否已经存在值。

class CreateProjectRequest implements RequestInterface
{
    #[Assert\NotBlank]
    #[Assert\Length(min: 10, max: 10)]
    public string $remoteSource;

    #[Assert\NotBlank]
    #[UniqueRemoteEntityConstraint]
    public string $remoteReference;
}

我的约束验证器UniqueRemoteEntityConstraint需要remoteSource的已验证值,然后才能继续检查其余部分。现在,我正在获取违规并检查remoteSource属性是否存在违规。

class UniqueRemoteEntityConstraintValidator extends ConstraintValidator
{
    /**
     * @param UniqueRemoteEntityConstraint $constraint
     */
    public function validate(mixed $value, Constraint $constraint): void
    {
        // Make sure `remoteSource` var is valid
        foreach ($this->context->getViolations() as $violation) {
            if ($violation->getPropertyPath() === 'remoteSource') {
                // Remote source not valid cancel
                return;
            }
        }
        
        // Do checks for uniqueness
    }
}

我相信这是粗略的,因为这取决于Symfony在我的DTO中检查属性的方式,它可能还没有验证它。是否有其他方法可以确保首先验证remoteSource属性?

tjrkku2a

tjrkku2a1#

看看这个问题和我的答案:
FunctionalTest Validator: Comparison with other property
您还可以直接在DTO上记录一个自定义验证器,从而可以访问所有属性。

示例

#[CustomConstraint]
class CreateProjectRequest implements RequestInterface
{
    public string $remoteSource;

    public string $remoteReference;
}

/**
 * @Annotation
 */
class CustomConstraint extends Constraint
{
    public function validatedBy(): string
    {
        return CustomValidator::class;
    }

    public function getTargets(): string
    {
        return self::CLASS_CONSTRAINT; // <<-- !!!!
    }
}

class CustomValidator extends ConstraintValidator
{
    /**
     * @param CreateProjectRequest $value
     * @param Constraint $constraint
     *
     * @return void
     */
    public function validate($value, Constraint $constraint)
    {
        // $value <--- CreateProjectRequest
                       
        $validator = Validation::createValidator();
        
        $violationRemoteSource = $validator->validate(
        $value->getRemoteSource(),
            [
                new NotBlank(),
                new Length()
            ]
        );
                
        $violationRremoteReference = $validator->validate(
            $value->getRremoteReference(),
            [
                new NotBlank(),
                mew UniqueRemoteEntityConstraint()
            ]
        );

        if ($violationRemoteSource->count() > 0
            || $violationRremoteReference->count() > 0
        ) {
            $this->context
                ->buildViolation(
                    'Not valid'
                )
                ->addViolation();
        }               
                       
    }
}

相关问题