Search code examples
phpsymfonysymfony-formssymfony5

"Expected argument of type "int or null", "object" given at property path


I'm learning Symfony recently. I encountered an error I couldn't find a serious answer when I called.

the error is this: Uncaught PHP Exception Symfony \ Component \ PropertyAccess \ Exception \ InvalidArgumentException: "Expected argument of type" int or null "," object "given at property path" parent_id "." at /home/vagrant/code/vendor/symfony/property-access/PropertyAccessor.php line 198

I have these codes in my controller file:

public function new(Request $request): Response
{
    $category = new Category();
    $form = $this->createForm(CategoryType::class, $category);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($category);
        $entityManager->flush();

        return $this->redirectToRoute('category_index');
    }

    return $this->render('category/new.html.twig', [
        'category' => $category,
        'form' => $form->createView(),
    ]);
}

My FormType file looks like this:

<?php

namespace App\Form;

use App\Entity\Category;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CategoryType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', null, [
                'attr' => ['class' => 'form-control'],
            ])
            ->add('slug', null, [
                'attr' => ['class' => 'form-control'],
            ])
            ->add('parent_id', EntityType::class, [
                'class' => Category::class,
                'choice_label' => 'name',
                'attr' => ['class' => 'form-control'],
                'placeholder' => 'Üst Kategori Seçiniz',

            ])
            ->add('title', null, [
                'attr' => ['class' => 'form-control']
            ])
            ->add('description', null, [
                'attr' => ['class' => 'form-control']
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Category::class,
            'required' => false

        ]);
    }
}

The content of my Entity file is below

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CategoryRepository")
 */
class Category
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $slug;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $parent_id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $title;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $description;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(?string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function setSlug(?string $slug): self
    {
        $this->slug = $slug;

        return $this;
    }

    public function getParentId(): ?int
    {
        return $this->parent_id;
    }

    public function setParentId(?int $parent_id): self
    {
        $this->parent_id = $parent_id;
        return $this;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): self
    {
        $this->description = $description;

        return $this;
    }

    public function __toString()
    {
        return $this->name;
    }

    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('name', new Assert\NotBlank());
        $metadata->addPropertyConstraint('title', new Assert\NotBlank());
        $metadata->addPropertyConstraint('description', new Assert\NotBlank());
        $metadata->addPropertyConstraint('slug', new Assert\NotBlank());
        $metadata->addConstraint(new UniqueEntity([
            'fields' => 'slug',
        ]));
    }
}

I will be grateful if you could help me. Conveniences ...


Solution

  • The problem is that you have not configured your entity or your form correctly. At the moment, in your entity parent_id is defined like this:

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $parent_id;
    

    while in your form, you expect another Category object there:

    ->add('parent_id', EntityType::class, [
        'class' => Category::class,
    

    You need to either make parent_id in your entity a one-to-many relationship (where one Category can be the parent category of another) or make that field in the form a regular ChoiceType and manually supply choices (by getting possible category ids from database). You would get those ids in the controller action and supply them to $this->createForm as a third parameter called options.