Символьная форма Поле Атрибут empty_data Игнорируется

В соответствии с Документация Symfony 2.4, любое поле формы, которое не требуется, но представлено без какого-либо значения (значение по умолчанию для полей выбора или пустое значение для текстовых полей), будет сохранено в сущности со значением NULL. Поэтому, если ваше поле объекта определено как NOT NULL (например, не nullable = true), когда вы сохраняете объект, вы получите неприятную ошибку:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'shell' cannot be null

Таким образом, в документации говорится, что если вы не хотите использовать значение NULL в качестве значения по умолчанию, вы можете указать атрибут empty_data в текстовом или поле выбора. Однако это не работает для меня.

Поле Entity (не может быть недействительным):

/**
 * @ORM\Column(type="string")
 */
protected $shell = '';

Form Builder (не требуется):

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

Я не понимаю этот атрибут empty_data? Я пропустил некоторые важные настройки в другом месте? Каков рекомендуемый способ сделать это?

UPDATE

Этот билет Github объясняет, что это была проблема еще в 2012 году, и она еще не исправлена.

Это означает, что все, кто использует построитель форм, вынуждены делать любое поле, которое не требуется в поле с нулевым значением? Это кажется довольно упрямым для рамки... есть много причин, по которым мы не хотим использовать NULL, когда значение по умолчанию '' или 0 не имеет уникального значения, и нам не нужен NULL. Для многих запросов необходимо проверить наличие обоих полей = 0 ИЛИ field = NULL, это боль.

Есть ли лучшее решение, которое используют другие люди?

Ответ 1

Я делаю это так, как предлагалось, но задает значение по умолчанию в классе Entity. Поэтому, чтобы установить значение null, Entity фиксирует, что он устанавливает 0 или что-то другое.

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

Или вы можете позаботиться об этом в настройщике:

public function setShell($shell) {
      $this->shell = $shell;

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

Может быть, не лучшая практика, но она работает, чтобы не иметь значений с нулевым значением.

Ответ 2

Другим возможным обходным решением является создание простого 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);

Ответ 3

Вы можете начиная с версии 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'
        ));

Ответ 4

  1. Не используйте опцию empty_data.
  2. И используйте атрибут placeholder.
  3. Пример:
    array(
       'label' => 'textExample',
        'required' => false,
        'disabled' => false,
        'read_only' => true,
        'attr' => array('placeholder' => 'DefaultValue')
        )