Symfony表单字段属性empty_data被忽略。

17
根据Symfony 2.4文档,任何非必填的表单字段,但在没有值的情况下提交(对于选择字段为默认值,对于文本字段为空值),将保存为具有NULL值的实体。因此,如果您的实体字段定义为NOT NULL(例如,不可为空= true),则持久化实体时会出现错误:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'shell' cannot be null

所以文档说如果您不想使用NULL作为默认值,您可以在文本或选择字段上指定“empty_data”属性。然而,这对我来说不起作用。
实体字段(非空):
/**
 * @ORM\Column(type="string")
 */
protected $shell = '';

表单生成器(非必需):

->add('shell', 'choice', array(
    'label' => 'Shell',
    'choices' => array('shell' => 'Fancy Pants'),
    'required' => false,
    'empty_data' => ''
))

我是否误解了empty_data属性?我是否错过了其他重要的设置?有没有推荐的做法?

更新

这个Github ticket解释说,这是2012年的一个问题,但现在还没有修复。

这意味着每个使用表单构建器的人都必须将任何不需要的字段变成可空字段吗?这对于框架来说似乎相当主观...有很多原因我们不想使用NULL,当默认值''或0没有独特含义且我们不需要NULL时。对于许多查询,必须检查field=0 OR field=NULL的存在是一种痛苦。

有其他人正在使用的更好的解决方案吗?


你找到解决这个问题的方法了吗? - greg
2
我最接近的方法是通过为empty_data添加一个空格来实现。'empty_data' => ' '。看起来有点hacky... - greg
@greg,这似乎仍然是一个没有在GitHub报告中活动的错误。如果您绝对需要将其设置为0,则下面的Anders提到了一个潜在的解决方法。我还没有测试过它。 - Chadwick Meyer
这个问题在3.2版本中可能被修复了吗? 因为我在3.2中没有遇到这个问题,而在3.0.9中我有(将值“”绑定到表单会将字段设置为NULL,而empty_data被设置为“”)。 - userfuser
4个回答

5

另一种可能的解决方法是创建一个简单的 DataTransfromer 并将其附加到所需的字段上。 例如:

<?php
namespace Interprac\Bundle\UtilityBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;

class NullToEmptyTransformer implements DataTransformerInterface
{
    /**
     * Does not transform anything
     *
     * @param  string|null $value
     * @return string
     */
    public function transform($value)
    {
        return $value;
    }

    /**
     * Transforms a null to an empty string.
     *
     * @param  string $value
     * @return string
     */
    public function reverseTransform($value)
    {
        if (is_null($value)) {
            return '';
        }

        return $value;
    }
}

将变压器附加到单个字段:

$nameSuffix = $builder->create('name_suffix', 'choice', array(
        'label'   => 'Name Suffix',
        'choices' => PR::getSMSFSuffixes(),
))->addModelTransformer(new NullToEmptyTransformer());

$builder->add($nameSuffix);

是的,我有一个类似的转换器用于其他情境。但这些属性在实体上非常常见,我真的希望不必手动将此转换器添加到我创建的每个表单字段中。很遗憾这不能默认工作。不过还是谢谢你的建议。 - Chadwick Meyer
是的,你必须明确地为每个所需字段设置它,这并不理想,但总比没有好。 - b.b3rn4rd
这个答案应该被标记为正确答案。虽然很长,但考虑到empty_data问题的缓慢解决进展,这是正确的做法。 - Luke
@Luke,谢谢老兄,在这个问题上感谢你的支持。复活节快乐! - b.b3rn4rd

5

我按照建议的方式进行操作,但在实体类中设置了默认值。因此,实体不会设置为null,而是将其设置为0或其他值。

public function __construct() { 
      $this->shell = 0;
}

或者,您可以在setter中处理它:
public function setShell($shell) {
      $this->shell = $shell;

      if ( !is_numeric($shell) ) {
             $this->shell = 0;
      }
      return $this;
}

也许不是最佳实践,但它可以避免出现可空值。

这是一个有趣的解决方法。我不太熟悉框架,不知道在构造函数中添加默认值是否会产生负面影响。其他人有什么看法吗? - Chadwick Meyer

1

从2.6版本开始,您可以在表单类中使用占位符和空数据的组合。

        $builderInterface->add('gender', 'choice', array(
            'required' => false,
            'choices' => array(
                'M'     => 'Male',
                'F'     => 'Female',
                'I'     => 'I dont want to specify'
            ),
            'placeholder' => 'Choose Gender',
            'empty_data'  => 'I'
        ));

1
  1. 不要使用empty_data选项。
  2. 同时使用placeholder属性。
  3. 例如:
    array(
       'label' => 'textExample',
        'required' => false,
        'disabled' => false,
        'read_only' => true,
        'attr' => array('placeholder' => 'DefaultValue')
        )


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接