mysqlsymfonydoctrine-ormsymfony4

Binding entities to query parameters only allowed for entities that have an identifier


I have a entity Annonce has Tags ManyToMany to Entity Tag

When i search an Annonce by tags like this picture

enter image description here

My probleme is : For example If the Bike tags exist in Database that will return Annonces with that tag, without errors

If I add for example Tags Like "Car" is ,no exist in database, an error is appear :

Binding entities to query parameters only allowed for entities that have an identifier.

This is in my controller

$annonces = $repository->findListByFilter($data->getTags());

and this is the repository

public function findListByFilter($tags):array
{
    return $this->createQueryBuilder('c')
        ->innerJoin('c.tags', 'tags')
        ->where('tags IN (:value)')
        ->setParameter(':value', $tags)
        ->getQuery()->getResult();
}

is there a solution to resolve this probleme?

Tag Entity

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

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

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

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

    public function getTitre(): ?string
    {
        return $this->titre;
    }

    public function setTitre(string $titre): self
    {
        $this->titre = $titre;

        return $this;
    }

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

Annonce Entity

namespace App\Entity;

use App\Tag\Taggable;
class Annonce
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    public function __construct()
    {

        $this->tags = new ArrayCollection();

    }

    use Taggable;
}

Class Taggable

use App\Entity\Tag;

trait Taggable
{

    /**
     * @var array
     *php bin/console make:entity --regenerate App
     * @ORM\ManyToMany(targetEntity="App\Entity\Tag", cascade={"persist"})
     */
    private $tags;

    /**
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getTags()
    {
        return $this->tags;
    }

    public function addTag(tag $tag)
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
        }
        return $this;
    }

    public function removeTag(tag $tag)
    {
        if ($this->tags->contains($tag)) {
            $this->tags->removeElement($tag);
        }

    }

    public function __construct()
    {
        $this->tags = new ArrayCollection();
    }
}

Solution

  • You can do either of these two options here:

    1. Store that new tag in DB also, then proceed with findListByFilter()

    2. Don't store the new tag, but modify:

    In controller:

    $annonces = $repository->findListByFilter($data->getTags());
    

    In repository:

    public function findListByFilter($tags):array
    {
        $tagsText = [];
        foreach ($tags as $tag) {
          $tagsText[] = $tag->getTitre();
        }
    
        return $this->createQueryBuilder('c')
            ->innerJoin('c.tags', 'tags')
            ->where('tags.titre IN (:value)')
            ->setParameter(':value', $tagsText)
            ->getQuery()->getResult();
    }
    

    I'm assuming here that the tag entity has the field text.