17

According to the Symfony 2.4 Documentation, any form field that is not required, but submitted without any value (default value for choice fields or empty value for text fields), will be saved to the entity with a NULL value. So if your entity field is defined as NOT NULL (e.g. not nullable=true), when you persist the entity you will get a nasty error:

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

So the documentation says that if you don't want it to use NULL as the default value, you can kindly specify the empty_data attribute on a text or choice field. However, this is not working for me.

Entity Field (not nullable):

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

Form Builder (not required):

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

Am I misunderstanding this empty_data attribute? Am I missing some important setting elsewhere? What is the recommended way of doing this?

UPDATE

This Github ticket explains that this was an issue back in 2012, and it hasn't been fixed yet.

That means that everyone who is using the form builder, is forced to make any field that is not required into a nullable field? That seems pretty opinionated for the framework... there are lots of reasons we don't want to use NULL when a default '' or 0 doesn't have unique meaning and we don't need a NULL. For many queries, having to check for the presence of both field=0 OR field=NULL, is a pain.

Is there some better solution other people are using?

4
  • Have you found any way around this problem? Commented Nov 28, 2014 at 1:05
  • 2
    The closest I've come is by adding adding one blank space for empty_data. 'empty_data' => ' '. Seems a bit hacky... Commented Nov 28, 2014 at 1:12
  • @greg This appears to still be a bug with no activity on that github report. Anders below mentions a potential work around if you absolutely need to set as 0. I have not tested that. Commented Dec 1, 2014 at 18:05
  • Is this issue possibly fixed in v3.2? Because I don't get it with 3.2, while on 3.0.9 I do (tying a value "" to a form, sets the field to NULL, while empty_data being set to ""). Commented Mar 27, 2017 at 11:27

4 Answers 4

5

I do it the way suggested, but sets a default value in the Entity class. So insted of setting null the Entity is fixing that it sets 0 or something others.

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

Or, you can take care of it in the setter:

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

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

Maybe not the best practice, but It works to not have nullable values.

Sign up to request clarification or add additional context in comments.

1 Comment

It's an interesting work around. I'm not familiar enough with the framework to know if adding that default in the construct will have negative consequences. Any others have an opinion about this?
5

Another possible workaround is to create a simple DataTransfromer and attach it to the required field. Example:

<?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;
    }
}

Attach the transformer to a single field:

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

$builder->add($nameSuffix);

4 Comments

Ya, I have a similar transformer for other contexts. But these types of properties are so common on entities, I really was hoping not to have to manually add this transformer to every single form field I create. Bummer that this doesn't work by default. Thanks for the suggestion though.
yeah, you have to explicitly specify set it for each required field, which is not ideal, but better than nothing.
This answer should be marked as the correct answer. It's lengthy but the correct thing to do considering the slow progress on this empty_data issue being fixed.
@Luke, thanks mate, appreciate your support on this matter. Happy Easter !
1

You can since 2.6, use a combination of placeholder and empty data in your form class.

        $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'
        ));

Comments

1
  1. Do not use empty_data option.
  2. And use the placeholder attribute.
  3. Ex:
    array(
       'label' => 'textExample',
        'required' => false,
        'disabled' => false,
        'read_only' => true,
        'attr' => array('placeholder' => 'DefaultValue')
        )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.