Cómo resolver la excepción de Symfony 5: Expected argument of type "string", "null" given at property path

Cómo resolver la excepción de Symfony 5: Expected argument of type "string", "null" given at property path

Después de meses de hacer lo mismo con Symfony una y otra vez, recibí un nuevo error que aún no habia visto. Este error suele ocurrir cuando no te concentras en lo que estás haciendo porque en realidad es un error conceptual. En mi caso, tengo un formulario simple que le permite al usuario cargar 2 imágenes, una imagen PNG y una imagen SVG y una descripción simple de la imagen. Ambas imágenes son necesarias, por lo que no puedes enviar el formulario si el usuario no selecciona las imágenes.

Conceptualmente hasta este punto, no hay nada de malo, ya que al enviar el formulario para crear una nueva entidad en la base de datos, funcionará sin ningún problema. Sin embargo, si editas la misma entidad y envías el formulario en la acción de edición de tu controlador, el error se activará si decides no cargar una imagen PNG o SVG. Esto sucede porque diseñé el sistema para que funcione así, ¡así que duh !.

En mi caso, ambas imágenes son obligatorias al enviar el formulario para crear una nueva entidad, sin embargo, los campos de la imagen podrían estar vacíos al actualizar la entidad. En tu caso, dependiendo de lo que hayas implementado, para solucionar la excepción tienes 2 opciones.

A. Definir la propiedad de empty_data en el tipo de formulario

La primera opción que puede resolver su problema es definir la propiedad empty_data en el campo con el problema en su FormType. Por ejemplo, en nuestro caso, el problema ocurre con 2 campos donde el usuario puede subir archivos:

<?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,
                // Registrar nueva clave "empty_data" con una cadena vacía
                'empty_data' => ''
            ])
            ->add('imageSvg', FileType::class, [
                'required' => false,
                'data_class' => null,
                // Registrar nueva clave "empty_data" con una cadena vacía
                'empty_data' => ''
            ])
            // ... //
        ;
    }

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

B. Aceptar el parámetro de cadena para que acepte valores NULL

Ahora, probablemente, la solución que funcionaría para todos, es simplemente definir el parámetro del método setter de la entidad que está causando el problema como uno nullable anteponiendo un signo de interrogación en el tipo de la variable:

// Acepta el parámetro de cadena que acepta valores NULL $imageSvg
public function setImageSvg(?string $imageSvg): self

Como la excepción siempre se activa al vincular los datos enviados al formulario en tu controlador (nuevo o editar según su caso):

<?php

namespace App\Controller;

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

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

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

    public function edit(Request $request, Images $image): Response
    {
        // La excepción se activará al vincular los datos enviados al formulario y a la entidad.
        $form = $this->createForm(ImagesType::class, $image);
        $form->handleRequest($request);
        
        // ... //
    }

    // ... //
}

Entonces, si te enfrentas a este problema después de agregar la llave empty_data, es muy probable que los setters se vean así:

<?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
{
    // .... ///
    // Tenga en cuenta el parámetro sin el ? como prefijo
    public function setImagePreview(string $imagePreview): self
    {
        $this->imagePreview = $imagePreview;

        return $this;
    }

    // Tenga en cuenta el parámetro sin el ? como prefijo
    public function setImageSvg(string $imageSvg): self
    {
        $this->imageSvg = $imageSvg;

        return $this;
    }

    // .... ///
}

Colocar el signo de interrogación ? antes de la cadena para indicar a PHP que el parámetro puede ser nulo:

<?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
{
    // .... ///
    
    // Permitir parámetro que acepta valores NULL
    public function setImagePreview(?string $imagePreview): self
    {
        $this->imagePreview = $imagePreview;

        return $this;
    }

    // Permitir parámetro que acepta valores NULL
    public function setImageSvg(?string $imageSvg): self
    {
        $this->imageSvg = $imageSvg;

        return $this;
    }

    // .... ///
}

Ten en cuenta que esto funcionará a nivel de entidad, pero si el campo en la base de datos no puede estar vacío y estableces el valor de ese campo como vacío, la inserción fallará por supuesto.

Que te diviertas ❤️!

Esto podria interesarte

Conviertete en un programador más sociable