php-ddd icon indicating copy to clipboard operation
php-ddd copied to clipboard

Using PHP7 type hinting with Symfony Form Text Type and empty_data returning NULL

Open webdevilopers opened this issue 9 years ago • 0 comments

Currently there is a issue with the Symfony Form Text Type and the empty_data option.

<?php

class ChangeInspectionDetails extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('problemNumber', TextType::class, [
                'empty_data' => '' // no effect
            ]);
    }
}

Though emtpy_data is set to an empty string the field will return null.

This can be a problem if you use PHP7 type hinting on your Domain Model:

<?php

class Contract
{
    public $problemNumber = ''; // no effect

    public function changeInspectionDetails(
        string $problemNumber = ''
    ) {
        $this->problemNumber = $problemNumber;

    }
}

You will get a Expected argument of type "string", "NULL" given.

There are some workarounds using Data Transformers until this issue eventually can be fixed. A custom TextType Extension suggested by @webmozart:

  • https://github.com/symfony/symfony/issues/5906#issuecomment-194201078

The fix "simply" is to explicitly type cast the value to a string before passing it to the method.

Most of the time I'm using Commands as data_class in my Forms:

<?php

class ChangeInspectionDetails extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('problemNumber', TextType::class, [
                'empty_data' => '' // no effect
            ]);
    }


    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => ChangeInspectionDetailsCommand::class
        ]);
    }    
}

This allows us to type cast in two places.

The Command:

<?php

class ChangeInspectionDetailsCommand
{
    public $problemNumber = ''; // no effect

    public function problemNumber()
    {
        return (string) $this->problemNumber; // workaround 1
    }
}

Or the Handler:

<?php

class ChangeInspectionDetailsHandler
{
    public function handle(ChangeInspectionDetailsCommand $command)
    {
        // ...
        $contract->changeInspectionDetails(
            #$command->problemNumber() // no effect
            (string) $command->problemNumber() // workaround 2
        );
    }
}

Hope this helps!

Gist:

  • https://gist.github.com/webdevilopers/8b7e874340823278ffcbe7face9517d2

Came from:

  • http://stackoverflow.com/questions/37577395/symfony3-form-component-trying-to-pass-null-to-a-type-hinted-method-in-php-7 @angelov
  • http://angelovdejan.me/2016/06/01/symfony3-form-component-and-type-hinting-in-php-7.html

Related issues:

  • https://github.com/symfony/symfony/issues/5906#issuecomment-174185006
  • https://github.com/symfony/symfony/issues/4715
  • https://github.com/webdevilopers/php-ddd/issues/5

webdevilopers avatar Jun 24 '16 09:06 webdevilopers