Symfony2表单将空字符串解释为空值

Jas*_*ett 14 symfony

我有一个包含各种字段的Symfony2表单,包括一个名为的可选文本字段recap.

recap当该字段中包含一些文本时,此字段可以完美保存,但当该字段留空时,我收到此错误:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'recap' cannot be null
Run Code Online (Sandbox Code Playgroud)

那是对的 - 专栏recap不可能null.我是故意这样设定的.Null意味着未知.当用户recap留空时,其值recap不是未知的; 它是空白的.

我的问题是如何让Symfony保存recap''空白,而不是null.

Ren*_*hle 15

转到您的实体并转到变量声明.

/**
 * @var string $name
 *
 * @ORM\Column(type="string", length=50)
 */
public $recap = '';
Run Code Online (Sandbox Code Playgroud)

您可以为$ recap指定默认值.

或者,当您拥有函数setRecap时,您可以检查是否为空,并设置您期望的值.

public function setRecap($recap) {
   $this->recap = !isset($recap) ? '': $recap;
}
Run Code Online (Sandbox Code Playgroud)

或者您将表单中的默认值类型设置为'',但我认为它不是您所期望的.

  • @ThomasDecaux:不,你_absolutely_可以修改"生成的"代码(甚至不一定需要生成).http://symfony.com/doc/current/book/doctrine.html#generating-getters-and-setters"此命令确保为Product类生成所有getter和setter.这是一个安全的命令 - 你可以一遍又一遍地运行它:它只生成不存在的getter和setter(即它不会替换你现有的方法)." 您不应该将实体视为一些Doctrine魔术,它们只是常规的PHP类. (6认同)
  • @ThomasDecaux:然后你应该使用doctrine;)那是错的...... Doctrine覆盖并只构建不存在的函数. (2认同)

Tho*_*aux 11

是的,在它上面浪费了很多时间;-("转换"在组件Form.php第1113行中是硬编码的!

private function viewToNorm($value)
{
    $transformers = $this->config->getViewTransformers();

    if (!$transformers) {
        return '' === $value ? null : $value;
    }

    for ($i = count($transformers) - 1; $i >= 0; --$i) {
        $value = $transformers[$i]->reverseTransform($value);
    }

    return $value;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,它是一个很大的错误(因为是DataTransformer的角色,而不是Form).因此,解决方案是创建自己的DataTransformer并将其与文本类型相关联.目前我正在与Symfony2失去这么多时间,总是在源头寻求这些小黑客;-(

  • 我正在接近记录一个关于此的错误,因为它似乎完全是愚蠢的.如果你仔细阅读他们的文档,它基本上说如果文本字段被标记为必需,空字符串将最终作为空字符串但是,如果该字段是可选的,则空字符串将被转换为"null".请参阅[empty_data](http://symfony.com/doc/current/reference/forms/types/text.html#empty-data)和[required](http://symfony.com/doc/current/reference/所需表格/类型/ text.html#). (3认同)

小智 7

我有另一个解决这个问题的方法:

创建虚拟课程

class EmptyString {
    public function __toString() {
        return '';
    }
}
Run Code Online (Sandbox Code Playgroud)

并设定

$builder->add('recap', 'text', [
    'empty_data' => new EmptyString(),
]);
Run Code Online (Sandbox Code Playgroud)

当实体将存储到DB时,它将自动转换为空字符串.


小智 5

我认为你正在做这个问题的错误的方式:当用户离开概括空白值未知的,因为没有提供.例如,你没有说空的生日字段意味着生日数字等于'',但生日数是未知的.地址等同样如此......

因此,如果您的用户不需要填写此字段,那么似乎最相关的响应实际上是将您的字段设置为可为空