Default API Filters Failing when referencing nested properties of related entities - symfony

I am configuring a series of ApiFilter classes from the Api-platform stack in a Symfony 4 application. I am finding that any filters using a nested property from an entity relationship takes no effect. Please see my example code below, would really appreciate any assistance with why it may not be working.
The entity I am trying to filter on is:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiProperty;
/**
* PostAuthor
* #ApiResource()
* #ORM\Table(name="POST_AUTHOR", indexes={#ORM\Index(name="IDX_CF3397D94A7000A0", columns={"IDENTITY_ID"})})
* #ORM\Entity(repositoryClass="App\Repository\PostAuthorRepository")
*/
class PostAuthor
{
/**
* #var string
*
* #ORM\Column(name="USER_ID", type="string", length=255, nullable=false)
* #ORM\Id
*/
private $userId;
/**
* #var string
*
* #ORM\Column(name="USERNAME", type="string", length=255, nullable=false)
*/
private $username;
And the collection I am filtering is:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiFilter;
use Symfony\Component\Serializer\Annotation\Groups;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter;
use Doctrine\ORM\Mapping as ORM;
/**
* PostHeader
* #ORM\Table(name="POST_HEADER", indexes={#ORM\Index(name="IDX_1CEEE7D0B65E5FF8", columns={"EMOTION_REF_ID"}), #ORM\Index(name="IDX_1CEEE7D08AFAAB14", columns={"AUTHOR_ID"})})
* #ORM\Entity(repositoryClass="App\Repository\PostHeaderRepository")
* #ApiResource(
* normalizationContext={"groups"={"postheader:read"}},
* denormalizationContext={"groups"={"postheader:write"}},
* )
* #ApiFilter(SearchFilter::class, properties={"author.userId": "partial", "author.username": "partial"})
*/
class PostHeader
{
/**
* #var PostAuthor
*
* #ORM\ManyToOne(targetEntity="PostAuthor")
* #ORM\JoinColumns({#ORM\JoinColumn(name="AUTHOR_ID", referencedColumnName="USER_ID")})
* #Groups({"postheader:read"})
*/
private $author;

I just test on a new project with the same classes than you and it works. I can filter by author.userId.
Please give us your testing request. And the error message ;).

Related

Symfony 5.4 problem with using Unique and Hostname together

I am trying to use Unique and Hostname constraint together in Syfony 5.4 entity. Lets have:
/**
* #ORM\Column(name="domain", type="string", length=150, nullable=false, unique=true)
* #Assert\NotBlank()
* #Assert\Hostname()
*/
private $domain;
This validate without problems. But when I add Unique constraint, it fails with message - This value should be of type array|IteratorAggregate.
/**
* #ORM\Column(name="domain", type="string", length=150, nullable=false, unique=true)
* #Assert\NotBlank()
* #Assert\Unique()
* #Assert\Hostname()
*/
private $domain;
I need both validation, yes, in this case it fails on database INSERT, but I want to validate form. How is correct way?
Thank you
DR
If I understand correctly you want to validate that the domain (or hostname) is unique inside the database table. In that case, you would have to use UniqueEntity see https://symfony.com/doc/current/reference/constraints/UniqueEntity.html.
It is worth mentioning that this doesn't protect you against race conditions.
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #UniqueEntity("domain")
*/
class YourEntity
{
/**
* #ORM\Column(name="domain", type="string", length=150, nullable=false, unique=true)
* #Assert\NotBlank()
* #Assert\Hostname()
*/
protected $domain;
}

Case mismatch between loaded and declared class names: "Doctrine\ORM\Mapping\ManytoOne" vs "Doctrine\ORM\Mapping\ManyToOne"

I am getting error of Case mismatch between loaded and declared class names: "Doctrine\ORM\Mapping\ManytoOne" vs "Doctrine\ORM\Mapping\ManyToOne" with User Entity only. Same Code with other entities is working fine.
Here is my Comp Entity
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Comp
*
* #ORM\Table(name="comp")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
*/
class Comp
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
* #ORM\ManytoOne(targetEntity="User")
* #ORM\JoinColumn(name="user_id",referencedColumnName="id", nullable=true)
*/
private $user;
My User Entity is
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
and I am getting error of
Case mismatch between loaded and declared class names: "Doctrine\ORM\Mapping\ManytoOne" vs "Doctrine\ORM\Mapping\ManyToOne"
while updating schema
The same code is working file with other entities. I manage to make foreign keys. Cannot understand what is going wrong with User field only.
try to change this:
* #ORM\ManytoOne(targetEntity="User")
to this:
* #ORM\ManyToOne(targetEntity="User")
Annotations are case sensitive for this reason you retrieve an error

Validate the combination of 2 filed in same Entity

I have an entity called Note , for every Note ther's etudiant_id and evaluation_id .
I want that the combination of etudiant_id and evaluation_id should be unique .
For exmple when i give him a Note object1(etudiant_id=1,evaluation_id=1) and Note2 object2(etudiant_id=1,evaluation_id=1) : this should throw an exception. but
in case of :
Note object1(etudiant_id=1,evaluation_id=2) and Note2 object2(etudiant_id=1,evaluation_id=1) : this will not throw anything .
By the way i tried :* #UniqueEntity(fields={"evaluation","etudiant"}) but this didnt work correcte.
Here's my Note Entity :
<?php
namespace EcoleBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Note
* #ORM\Entity
* #UniqueEntity(fields={"evaluation","etudiant"})
* #ORM\Table(name="note")
* #ORM\Entity(repositoryClass="EcoleBundle\Repository\NoteRepository")
*/
class Note
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="valeur", type="float", nullable=true)
*/
private $valeur;
/**
* #ORM\ManyToOne(targetEntity="EcoleBundle\Entity\Evaluation", inversedBy="notes")
*/
private $evaluation;
/**
* #ORM\ManyToOne(targetEntity="EcoleBundle\Entity\Etudiant", inversedBy="notes")
*/
private $etudiant;
You should have only one #Entity annotation. Try to substitute with this and clean the cache
/**
* Note
* #ORM\Entity(repositoryClass="EcoleBundle\Repository\NoteRepository")
* #UniqueEntity(fields={"evaluation","etudiant"})
* #ORM\Table(name="note")
*/

Symfony2 Doctrine2 ManyToMany Composite key Column name referenced does not exist

I have a ManyToMany relation with a composite key on the reverse side.
When I use the console command doctrine:schema:update I have the following error:
[Doctrine\ORM\ORMException]
Column name `keyword` referenced for relation from Map\MapBundle\Entity\
Student towards Map\MapBundle\Entity\SkillType does not exist.
I have an entity student (unique key) with a ManyToMany relation with an entity skill (composite key) which has a ManyToOne relation with skillType (unique key).
Here is the different class mapping I have:
Class Student
<?php
namespace Map\MapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Student
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Map\MapBundle\Entity\StudentRepository")
*/
class Student {
/**
*
* #var integer #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Map\MapBundle\Entity\SkillType")
* #ORM\JoinTable(name="students_skills",
* joinColumns={
* #ORM\JoinColumn(name="keyword", referencedColumnName="keyword"),
* #ORM\JoinColumn(name="attribut", referencedColumnName="attribut")
* })
*/
private $skills;
}
Class skill
<?php
namespace Map\MapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Skill
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Map\MapBundle\Entity\SkillRepository")
*/
class Skill {
/**
* #ORM\ManyToOne(targetEntity="Map\MapBundle\Entity\skillType")
* #ORM\JoinColumn(name="keyword", referencedColumnName="keyword")
* #ORM\Id
*/
private $keyword;
}
Classe skillType
<?php
namespace Map\MapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* SkillType
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Map\MapBundle\Entity\SkillTypeRepository")
*/
class SkillType {
/**
* #var string
*
* #ORM\Column(name="keyword", type="string", length=255)
* #ORM\Id
*/
private $keyword;
}
I tried to exchange the keyword and attribut #joinColumn lines, but I have the same error message with attribut instead of keyword.
I can't see what's wrong with my mapping. The table skill exists and has columns named keyword and attribut.
I hope that somebody will see where I made a mistake (probably a typo error like a missing character or a case mistake).
Thank you for your answer. It helped me a lot and i succeded doing the schema update.
Here is the code I finaly used
/**
* #ORM\ManyToMany(targetEntity="Carte\CarteBundle\Entity\Skill")
* #ORM\JoinTable(name="students_skills",
* joinColumns={#ORM\JoinColumn(name="student_id", referencedColumnName="id")},
* inverseJoinColumns={
* #ORM\JoinColumn(name="keyword", referencedColumnName="keyword"),
* #ORM\JoinColumn(name="attribut", referencedColumnName="attribut")
* })
*/
private $skills;
You write that you want Student to have the many-to-many relation with Skill, but you connected it with SkillType instead. And you're missing the inverseJoinColumns property and you didn't referenced Student properly.
Try the following annotation (untested and after looking at the documentation):
/**
* #ORM\ManyToMany(targetEntity="Map\MapBundle\Entity\Skill")
* #ORM\JoinTable(name="students_skills",
* joinColumns={#ORM\JoinColumn(name="student_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="skill_keyword", referencedColumnName="keyword")}
* )
*/
private $skills;

how to extend an entity from one bundle to another bundle

i have an already created symfony bundle. i wanted to add another bundle for my application separately. so now im facing a problem that how to extend an entity from old bundle to newly created one. i extended it normally but it giving errors.
i have these 2 bundles,
MyFirstBundle
MySecondBundle
MyFirstBundle entity,
namespace My\FirstBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
*
* #ORM\Table(name="companies")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Company
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #Groups({"list_companies", "company_details", "ad_details"})
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=50, nullable=true)'
*
* #Groups({"ad_details"})
*/
private $name;
MySecondBundle Entity,
namespace My\SecondBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use My\FirstBundle\Entity\Company as BaseCompany;
class Companies extends BaseCompany
{
public function __construct() {
parent::__construct();
}
}
im not sure that i can extend my entity like this. im getting error when creating forms with this entity
Class "MySecondBundle:companies" seems not to be a managed Doctrine entity. Did you forget to map it?
You need to add the doctrine annotations for the second entity as well.
/**
*
* #ORM\Table(name="companies")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Companies extends BaseCompany
{
public function __construct() {
parent::__construct();
}
}

Resources