Symfony表单不变字段返回验证类型错误

时间:2019-06-24 10:38:35

标签: php symfony symfony-forms symfony-4.3

尝试更新实体,并提交值不变的字段会导致类型错误。我在做什么错了?

实体:

<?php

namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;
...
class User implements UserInterface
{
...

    /**
     * @ORM\Column(type="bigint", nullable=true)
     * @Groups({"default", "listing"})
     * @Assert\Type("integer")
     */
    private $recordQuota;

...

FormType:

<?php

namespace App\Form;

...

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
...
            ->add('recordQuota', IntegerType::class)
        ;
    }

...
}

控制器:

...
    /**
     * @Route("/api/user/{id}", name="editUser")
     * @Method({"PUT", "PATCH"})
     * @Rest\View()
     */
    public function updateAction(Request $request, User $user)
    {
        $form = $this->createForm(UserType::class, $user);
        $data = $request->request->get('user');
        $clearMissing = $request->getMethod() != 'PATCH';

        $form->submit($data, $clearMissing);


        if ($form->isSubmitted() && $form->isValid()) {
...

我正在使用PostMan提交表单数据。 如果我要更新的实体的recordQuota为1000,那么我将提交具有不同值的表单。一切都能正常工作和更新。

但是,如果我使用recordQuota:1000提交表单,则该值应保持不变,我将得到一个错误的类型错误:

            "recordQuota": {
                "errors": [
                    "This value should be of type integer."
                ]
            }

其他信息:

我使用$form->submit而不是handleRequest,因为我使用的是补丁程序。因此,我需要能够启用/禁用$clearMissing。但是,即使使用handleRequest也会产生相同的问题。

即使在将recordQuota传递给表单之前,将它的类型转换为int仍然失败。

如果我从窗体和实体中删除了所有类型信息,则在实际进行更改时会收到“此值应为字符串类型”。

2 个答案:

答案 0 :(得分:0)

编辑:请注意,如果字段类型为TextType,则以下内容是正确的,但是IntegerType@Assert\Type("integer")可以正常工作。哪种会使我的答案无效/不相关...

您正在使用@Assert\Type("integer")批注,但这意味着:

  • 值必须是整数-作为PHP类型,例如调用is_int($value)
  • 并且由于数据来自表单(就像我在您的代码中看到的那样,可能没有任何转换器),所以它的类型为string
  • 因此,验证始终会失败

您需要的是@Assert\Type("numeric")

  • 它等效于is_numeric($value)
  • 在到达实体字段时会转换为字符串

答案 1 :(得分:0)

这是与此处所述的Symfony 4.3验证程序auto_mapping结合使用的问题: https://symfony.com/blog/new-in-symfony-4-3-automatic-validation

制造商捆绑包将错误的类型转换添加到bigint字段。

请参阅此处: https://github.com/symfony/maker-bundle/issues/429

答案是将实体中的获取器和设置器更改为:

    public function getRecordQuota(): ?int
    {
        return $this->recordQuota;
    }

    public function setRecordQuota(?int $recordQuota): self
    {
        $this->recordQuota = $recordQuota;

        return $this;
    }

    public function getRecordQuota(): ?string
    {
        return $this->recordQuota;
    }

    public function setRecordQuota(?string $recordQuota): self
    {
        $this->recordQuota = $recordQuota;

        return $this;
    }

或者,可以在验证器配置中关闭auto_mapping。