如何使用 symfony/validator 验证不可更新的列?

问题描述 投票:0回答:2

我有一个列,它是 DateTimeImmutable,当用户加入平台时保存。我正在进行 phpunit 测试,我想验证该列是否无法更新。我想在出现 SQL 错误(尝试更新列时出错)之前检测到错误。

 #[ORM\Column(updatable: false)]
    #[Assert\Type(
        type: 'object',
        message: 'The value {{ value }} is not a valid {{ type }}.'
    )]
    private ?\DateTimeImmutable $joinedAt = null;

我尝试更新实体列,然后调用 $manager->persist($entity) 看看当时是否有错误,但没有任何反应。

  public function testInvalidJoinedAt(): void
    {
        $manager = static::getContainer()->get(EntityManagerInterface::class);

        // User joinedAt cannot be updated
        $now = new DateTimeImmutable();
        $existingUser = $this->getRepository(UserRepository::class)->find(0);
        $existingUser->setJoinedAt($now);

        try {
            $manager->persist($existingUser);
        } catch (\Throwable $err) {
            $this->assertEquals('???', $err->getMessage());
        }
    }

像“#[Assert\NotUpdatable]”这样的断言类型将是完美的解决方案,但没有这样的东西。

php symfony validation doctrine phpunit
2个回答
0
投票

您可以创建自己的自定义验证器,在此处查看文档在此处输入链接描述 在你的 src/Validator/Constraints 添加文件 1)

class fileName extends Constraint
{
    public $message = 'Error Message Goes here for not modifd property';
}
 class FileName extends ConstraintValidator
 {
     public function validate($value, Constraint $constraint)
     {
         if ($value !== null) {
         $this->context->buildViolation($constraint->message)->addViolation();
     }
   }
 }
  1. 您可以将自定义验证器添加到实体断言中

    /**
      * @ORM\Column(updatable=false)
      * @customValidator\validatorName
      */
     private ?\DateTimeImmutable $joinedAt = null;
    

0
投票

Doctrine 不验证 Symfony Validation 属性。在保存之前,您必须使用 Symfony 验证器验证实体。

使用自定义验证器,您需要知道它是插入还是更新,因为 Symfony 验证器不知道您是在执行插入还是更新。这样就可以创建这样一个自定义验证器。但这是一个更大的努力。

我会根据你的方法解决它

testInvalidJoinedAt()
所以你不必验证。

namespace App\Entity;

use Doctrine\ORM\Mapping\Column;

class Entity
{
    #[Column(updatable: false)]
    private ?\DateTimeImmutable $joinedAt = null;

    public function getJoinedAt(): ?\DateTimeImmutable
    {
        return $this->joinedAt;
    }

    public function setJoinedAt(?\DateTimeImmutable $joinedAt): void
    {
        if (!$this->joinedAt instanceof \DateTimeImmutable) {
            $this->joinedAt = $joinedAt;
        }
    }
}

单元测试示例

class EntityTest extends TestCase
{
    public function testNewEntity() {
        $dateTime = new DateTimeImmutable();
        $entity = new Entity();
        $entity->setJoinedAt($dateTime);
        $this->assertEquals($dateTime, $entity->getJoinedAt());
    }

    public function testEntityFromDatabase() {
        // Mock entity from database
        $dateTime = new DateTimeImmutable();
        $dateTime->setDate(2022, 9, 17)->setTime(19, 31, 41);
        $entityFromDatabase = new Entity();
        $entityFromDatabase->setJoinedAt($dateTime);

        // Set joinedAt update
        $entityFromDatabase->setJoinedAt(
            (new DateTimeImmutable())->setDate(2023, 10, 19)->setTime(8, 11, 15)
        );

        $this->assertEquals($dateTime, $entityFromDatabase->getJoinedAt());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.