0

I have a MainConfig entity that has One-to-one relationship with LedConfig entity. LedConfig can be null.

<?php

namespace ...


use Doctrine\ORM\Mapping as ORM;
...

/**
 * @ORM\Entity
 */
class MainConfig
{

    ...

    /**
     * @ORM\OneToOne(targetEntity="...\LedConfig", cascade={"all"})
     * @ORM\JoinColumn(name="led_config_id", referencedColumnName="id", nullable=true, unique = true)
     */
    private $ledConfig = null;

    ...

}

<?php

namespace ...


use Doctrine\ORM\Mapping as ORM;
...

/**
 * @ORM\Entity
 */
class LedConfig
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;


    /**
     * @ORM\Column(type="float")
     * @Assert\Type(type="float")
     */
    private $lowerVoltageThreshold = 11.9;

    /**
     * @ORM\Column(type="float")
     * @Assert\Type(type="float")
     */
    private $upperVoltageThreshold = 12.85;


}

<?php

namespace ...;

use Symfony\Component\Form\AbstractType;
...

class MainConfigType extends AbstractType
{
    ...

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(...)
            ->add('ledConfig', LedConfigType::class)
            ...
    }
    ...
}

I am inserting a main config into a database automatically without using Symfony forms. So, if I set led config to null in the code - field led_config_id inside main config table is correctly set to NULL.

But, when I am updating the main config, I am using HTTP PUT request that is processed through Symfony forms. I am using JSON, so request body looks like this:

{..., "ssid":"test","runningMode":"force_on","led_config":null, ...}

After the form is processed, property $ledConfig inside MainConfig entity is magically instantiated as LedConfig object with all properties set to NULL?! And database update fails because it tries to save LedEnttiy with empty fields. Why does it happen?

Can someone please help me and indicate what I did wrong?

EDIT: I could hack it in the controller update action, after the form validation:

/**
 * @Route("...")
 * @Method("PUT")
 */
public function updateMainConfigAction($id, Request $request)
{
    $requestData = \GuzzleHttp\json_decode($request->getContent(), true);

    ...

    if (!$form->isValid()) {
        throw $this->throwApiProblemValidationException($form);
    }

    if (empty($requestData['led_config'])) {
        $mainConfig->setLedConfig(null);
    }

    $em = $this->getDoctrine()->getManager();
    $em->persist($mainConfig);
    $em->flush();

    ...

}

but that is kind of dirty...

Matko Đipalo
  • 1,676
  • 1
  • 11
  • 23

1 Answers1

2

There are the empty_data and the required options on Symfony's FormType.

The empty_data option has following behaviour:

  1. when data_class is set and required option is true, then empty_data is new $data_class();
  2. when data_class is set and required option is false, then empty_data is null;
  3. when data_class is not set and compound option is true, then empty_data is empty array;
  4. when data_class is not set and compound option is false, then empty_data is empty string.

The required option is true by default and the data_class is set on the ledConfig field, so when you left it empty, then new class is set to it. If you want the ledConfig field to be explicitly set to null when no value is selected, you can set directly the empty_data option.

In your case, you want the #2 scenario, so set required option to false and empty_data option set to null on ledConfig field:

...
$builder
    ->add(...)
    ->add('ledConfig', LedConfigType::class, array(
        'required' => false
        'empty_data' => null
    ))
    ...
Jan Rydrych
  • 2,188
  • 2
  • 13
  • 18
  • Hm... I already tried with `...array('required' => false)`, but no help. – Matko Đipalo Mar 20 '17 at 12:12
  • Even though, in a theory, it should work XD I must more carefully investigate code. – Matko Đipalo Mar 20 '17 at 12:19
  • 1
    And did you tried to set the `empty_data` option to `null` on ledConfig field? – Jan Rydrych Mar 20 '17 at 15:22
  • It works if I set `->add('ledConfig', LedConfigType::class, array('required' => false, 'empty_data' => null))`. I'll accept your answer, but please update code, so if anybody else would have the same problem, they don't need to read comments to find out correct solution :) Tnx! – Matko Đipalo Mar 21 '17 at 10:26