How to solve Symfony 5 exception: Expected argument of type "string", "null" given at property path

How to solve Symfony 5 exception: Expected argument of type "string", "null" given at property path

After months of doing the same stuff with Symfony over and over again, I got a new error that I haven't seen yet. This error usually happens when you don't concentrate on what you are doing because it's actually a conceptual error. In my case, I have a simple form that allows the user to upload 2 images, a PNG image, and an SVG image and a simple description of the image. Both images are required, so you cannot submit the form if the user doesn't select the images.

Conceptually till this point, there's nothing wrong as when submitting the form to create a new entity on the database, it will work without any issue. However, if you edit the same entity and submit the form on the edit action of your controller, the error will be triggered if you decide to don't upload either a PNG or SVG image. This happens because I designed the system to work like that, so duh!.

In my case, both images are required when submitting the form to create a new entity, however, the image fields could be empty when updating the entity. In your case, depending on what you implemented, to solve the exception you have 2 options.

A. Define the empty data property on the form type

The first option that may solve your problem, is to define the empty_data property on the field with the problem in your FormType. For example, in our case, the problem happens with 2 fields where the user can upload files:

<?php

namespace App\Form;

use App\Entity\Images;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

use Symfony\Component\Form\Extension\Core\Type\FileType;

class ImagesType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ... //
            ->add('imagePreview', FileType::class, [
                'required' => false,
                'data_class' => null,
                // Register new key "empty_data" with an empty string
                'empty_data' => ''
            ])
            ->add('imageSvg', FileType::class, [
                'required' => false,
                'data_class' => null,
                // Register new key "empty_data" with an empty string
                'empty_data' => ''
            ])
            // ... //
        ;
    }

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

B. Accept nullable string parameter

Now probably the solution that would work for everyone, is to simply define the parameter that the setter method of the entity that is causing the problem as nullable putting before a question mark in the type of the variable:

// Accept nullable string parameter $imageSvg
public function setImageSvg(?string $imageSvg): self

As the exception is always triggered when binding the submitted data to the form in your controller (new or edit according to your case):

<?php

namespace App\Controller;

// Controller
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

// Entities
use App\Entity\Images;
use App\Form\ImagesType; 

class ImagesController extends AbstractController
{   
    // ... //

    public function edit(Request $request, Images $image): Response
    {
        // The exception will be triggered when binding the submitted data to the form and the entity
        $form = $this->createForm(ImagesType::class, $image);
        $form->handleRequest($request);
        
        // ... //
    }

    // ... //
}

So if you are facing this issue after adding the empty_data key, it's very probable that your setters look like this:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Images
 *
 * @ORM\Table(name="images", indexes={@ORM\Index(name="author_id", columns={"author_id"})})
 * @ORM\Entity(repositoryClass="App\Repository\ImagesRepository")
 */
class Images
{
    // .... ///
    // Note the parameter without the ? prefix in string
    public function setImagePreview(string $imagePreview): self
    {
        $this->imagePreview = $imagePreview;

        return $this;
    }

    // Note the parameter without the ? prefix in string
    public function setImageSvg(string $imageSvg): self
    {
        $this->imageSvg = $imageSvg;

        return $this;
    }

    // .... ///
}

Place the question mark ? before string to indicate to PHP that the parameter can be null:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Images
 *
 * @ORM\Table(name="images", indexes={@ORM\Index(name="author_id", columns={"author_id"})})
 * @ORM\Entity(repositoryClass="App\Repository\ImagesRepository")
 */
class Images
{
    // .... ///
    
    // Allow nullable parameter
    public function setImagePreview(?string $imagePreview): self
    {
        $this->imagePreview = $imagePreview;

        return $this;
    }

    // Allow nullable parameter
    public function setImageSvg(?string $imageSvg): self
    {
        $this->imageSvg = $imageSvg;

        return $this;
    }

    // .... ///
}

Note that this will work at the entity level, but if the field in the database cannot be empty and you set the value of that field as empty, the insertion will fail of course.

Happy coding ❤️!

This could interest you

Become a more social person