ManyToMany bidirectional [Semantical Error] User has no association named service - symfony

I have two netities user & service and the join table user_service generated by doctrine, i tried to add a manytomany relatioship here is the annotations that i added :
Entity User side :
/**
* #ORM\ManyToMany(targetEntity="Service", inversedBy="users")
* #ORM\JoinTable(name="user_service",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="service_id", referencedColumnName="id")}
* )
*/
protected $services;
Entity Service side :
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="services")
*/
protected $users;
Everything seems to work fine, but when i make this request :
$query = $em->createQuery(
'SELECT u
FROM ApplicationFrontBundle:User u
JOIN u.service s
WHERE u.id = :id
'
)->setParameters(array('id'=> $id));
$services = $query->getArrayResult();
I have this error :
[Semantical Error] line 0, col 91 near 's
': Error: Class Application\FrontBundle\Entity\User has no association named service
But when i do it by the objects it works, the problem is that it executes a lot of requests

Because you named it serviceSSS?
$query = $em->createQuery(
'SELECT u
FROM ApplicationFrontBundle:User u
JOIN u.services s
WHERE u.id = :id
'
)->setParameters(array('id'=> $id));
$services = $query->getArrayResult();

Related

symfony doctrine one-to-many entity setup

I'm trying to get my head around the entity annotations for a doctrine one to many relationship.
For example, if table_one (T1) is:
email_address (string)
and table_two (T2) is
userid_email (string)
entry (int)
(email_address.table_one = userid_email.table_two) and there are multiple entries in table_two i.e
userid_email=test#email.com,entry=5;
userid_email=test#email.com,entry=6
Do I create the annotation for the T1 Entity
/**
* #ORM\ManyToMany(targetEntity="T1")
* #ORM\JoinTable(name="table_two",
* joinColumns={#ORM\JoinColumn(name="userid", referencedColumnName="userid_email")}
* )
*/
protected entries;
public function __construct()
{
$this->entries = new ArrayCollection();
}
And then in a createQuery I query on T1 :
$query = $em->createQuery('
SELECT u.email, u.entries
FROM AppBundle:T1 u
WHERE u.email = :an_email_address');
For the above query I would always get this error :
Error: Invalid PathExpression. Must be a StateFieldPathExpression
Is there something I am setting up improperly for the relationship?
Your configuration seems to be wrong, try something like:
/**
* #ORM\ManyToMany(targetEntity="T1")
* #ORM\joinColumn={#ORM\JoinColumn(name="userid", referencedColumnName="userid_email")}
* )
*/

Doctrine Query Builder for entities with Join Table

User ---[OneToMany]---> AcquiredSkill ---[ManyToOne]---> Skill
I'm having problems with creating a query using query builder in doctrine. Can someone help me convert this mysql query to a doctrine query using query builder?
SELECT u.*, s.*
FROM `user` u
Join `acquired_skill` ac ON ac.user_id = u.user_id
Join `skill` s ON ac.skill_id = s.skill_id
Tables
user
- user_id
- name
skill
- skill_id
- skill_name
acquired_skill
- as_id
- skill_id
- user_id
So far, this is my query but it lacks the join between the skills.
createQueryBuilder('u')
->select('u.user_id', 'u.name')
->getQuery()
->getResult();
Your relation seems like you have many-to-many association between user and skills you can set your entities to setup this relation like user entity will point to skill entity in a many-to-many way
User Entity
/**
* #ORM\ManyToMany(targetEntity="Namespace\YourBundle\Entity\Skill", cascade={"persist"})
* #ORM\JoinTable(name="acquired_skill",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="skill_id", referencedColumnName="id")}
* )
*/
private $skills;
Skill Entity
/**
*
* #ORM\ManyToMany(targetEntity="Namespace\YourBundle\Entity\User", mappedBy="skills")
*/
private $user;
Now in query builder you can join your user entity with skill like below
$this->createQueryBuilder('u')
->select('u')
->innerJoin('u.skills','s')
->getQuery()
->getResult();
for further clarification see docs 22.2.19. #ManyToMany
$qb = $this->entity_manager->createQueryBuilder('u');
$qb->select("*");
$qb->innerJoin('Namespace\YourBundle\Entity\Aq_skill', 'ac', 'WITH', 'ac.user_id = u.user_id');
$qb->innerJoin('Namespace\YourBundle\Entity\skill', 's', 'WITH', 'ac.skill_id = s.skill_id');
$result = $qb->getQuery()->getArrayResult();

Doctrine n:m relation Undefined index: joinColumns in BasicEntityPersister.php

My question is strongly related to this one Undefined index: inverseJoinColumns while trying to define ManyToMany relationship between two entities
I am trying to find all the books which have no section. ->findBy(array("section"=>null)
Here is my Entity config:
EditedBooks
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Sections", inversedBy="editedBook")
* #ORM\JoinTable(name="edited_book_has_section",
* joinColumns={
* #ORM\JoinColumn(name="edited_book_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="section_id", referencedColumnName="id")
* }
* )
*/
private $section;
Here is my Entity config:
Sections
/**
* Bidirectional (INVERSE SIDE)
*
* #ORM\ManyToMany(targetEntity="EditedBooks", mappedBy="section")
*/
private $editedBook;
The Error that I am getting
Undefined index: joinColumns in BasicEntityPersister.php
I tryied it also with only
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Sections", inversedBy="editedBook")
* #ORM\JoinTable(name="edited_book_has_section")
*/
or switching the definition but then I receive this error
You cannot search for the association field '\Entity\EditedBooks#section', because it is the inverse side of an association. Find methods only work on owning side associations.
Workaround:
Today I tried to fix my problem with the querybuilder in my editedBooksRepository
$query = $qb->select('books')
->from('Bundle:EditedBooks', 'books')
->leftJoin('books.section', 'sec')
->addSelect('COUNT(sec.id) AS sec_count')
->andWhere('sec_count = 0');
But I receved the following error:
An exception occurred while executing 'SELECT e0_.id AS id0, e0_.doi
AS doi1, e0_.isbn_print AS isbn_print2, e0_.isbn_electronic AS
isbn_electronic3, e0_.publication_date AS publication_date4,
e0_.price_print AS price_print5, e0_.price_electronic AS
price_electronic6, e0_.summary AS summary7, e0_.title AS title8,
e0_.ongoing AS ongoing9, e0_.pages AS pages10, e0_.illustrations AS
illustrations11, e0_.entry_date AS entry_date12, e0_.google_id AS
google_id13, e0_.specialIssue_comment AS specialIssue_comment14,
e0_.deleted AS deleted15, e0_.specialIssue_id AS specialIssue_id16,
COUNT(s1_.id) AS sclr17, e0_.book_series_id AS book_series_id18,
e0_.copyright_id AS copyright_id19, e0_.publisher_id AS publisher_id20
FROM edited_books e0_ LEFT JOIN edited_book_has_section e2_ ON e0_.id
= e2_.editedbooks_id LEFT JOIN sections s1_ ON s1_.id = e2_.sections_id WHERE sclr17 = 0':
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sclr17' in
'where clause'
but to me it seems like sclr17 exists, am I missing something?
The ugly Workaround
I know it is not the right thing to do but sometimes a man has to to what a man has to do:
$noSection = new Sections();
$noSection->setTitle("Sectionless");
//add all the books
$noSection->setEditedBook(new ArrayCollection($books));
//remove the assigned ones
foreach($sections as $section){
$sBooks = $section->getEditedBook();
foreach($sBooks as $b){
$noSection->removeEditedBook($b);
}
}
With the dirty fix it is now working but I am glad for any other solution.
Here is a working example
class Audio
{
/**
* #ORM\ManyToMany(targetEntity="Acme\MyBundle\Entity\Groupe",inversedBy="audios")
*/
private $groupes;
class Groupe
{
/**
* #ORM\ManyToMany(targetEntity="Acme\MyBundle\Entity\Audio",mappedBy="groupes")
*/
private $audios;
Notice how the mappedby and inversedby, as well at the attributes have an "s" at the end. (Groupe => private $groupe s ). Maybe it will help you
Can't you just check with null?
$query = $qb->select('books')
->from('Bundle:EditedBooks', 'books')
->leftJoin('books.section', 'sec')
->where('sec IS NULL');

Symfony2 and Doctrine - Error: Invalid PathExpression. Must be a StateFieldPathExpression

I have an entity that looks like this:
/**
* #Gedmo\Tree(type="nested")
* #ORM\Table(name="categories")
* #ORM\Entity()
*/
class Category extends BaseCategory
{
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
*/
protected $children;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $parent;
}
and I am trying to run a query like this:
$qb = $this->em->createQueryBuilder()
->select('c.parent')
->from('Category', 'c');
$result = $qb->getQuery()->getArrayResult();
However, I am getting the following error:
[Semantical Error] ... Error: Invalid PathExpression. Must be a StateFieldPathExpression.
How can I select the parent_id field from my table. I have tried a bunch of variations and even if I do something like this:
$qb = $this->em->createQueryBuilder()
->select('c')
->from('Category', 'c');
I get all fields in the table except for the parent_id. This seems like Doctrine is getting in the way. How can I query for this parent_id field? or better yet how can I get all fields in the table including the parent_id
You can use the currently undocumented IDENTITY function to select the FK IDs in a query:
SELECT IDENTITY(c.parent) ...
Solution using createQueryBuilder:
$query->SELECT('pa.id')
->from('Category', 'ca');
$query->join('ca.parent', 'pa');
$result = $query->getQuery()->getArrayResult();
You are selecting an object that is not joined.
Like said in another answer, you have to do something like :
qb->innerJoin("c.parent", "p")
You can change it like this:
->select(array('i.id','identity(i.parent) parent','i.nom'))

Symfony2 building ManyToOne relationship in Entities

I have two entities in a OneToMany relationship, Perfil and IPerfil. Perfil can have several IPerfil's associated:
>
class Perfil
{
/**
* #var integer $id
*
* #ORM\Column(name="id_perfiles", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="P360.perfiles_seq")
* #ORM\OneToMany(targetEntity="IPerfil", mappedBy="id")
*/
private $id;
And the other one:
>
class IPerfil
{
/**
* #var integer $id
* #ORM\ManyToOne(targetEntity="Perfil")
* #ORM\JoinColumn(name="id_perfiles", referencedColumnName="id_perfiles", onDelete="CASCADE")
*/
protected $id;
I'm able to lazyload from IPerfil to Perfil, but not in the other direction (from Perfil to IPerfil), but if I can't do any DQL over IPerfil or createQueryBuilder()->setPameter... Symfony will always return an error like this:
[Semantical Error] line 0, col 9 near 'id_perfiles FROM': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
If I define the field Id with an
#ORM\Column(name="id_perfiles", type="integer")
Then I'm able to build DQL's with the entity, but the relationship won't work anymore.
I'm lost around here... It seems I'm missing something in the relationship definition, but have no clue.
Thanks in advance for any tip.
EDIT
If I use:
$entities=$em->getRepository('usuariosBundle:IPerfil')->findAll(array());
It doen'st gives an error, but I need to filter and order the results.
$entities=$em->getRepository('usuariosBundle:IPerfil')->findBy(array(),array('id' => 'asc', 'descripcion' => 'asc'));
Unrecognized field: id
$query=$em->getRepository('usuariosBundle:IPerfil')->createQueryBuilder('p')
->orderBy('id', 'ASC')
->getQuery();
$entities = $query->getResult();
*[Semantical Error] line 0, col 60 near 'id ASC': Error: 'id' is not defined. *
$entities = $this->get('doctrine')->getEntityManager()->createQuery('SELECT p.id FROM usuariosBundle:IPerfil p ')->getResult();
[Semantical Error] line 0, col 9 near 'id FROM usuariosBundle:IPerfil': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
Use attribute name of class, no column name on dql => 'id'
->orderBy('p.id', 'ASC') and ->createQuery('SELECT p FROM usuariosBundle:IPerfil p ')->getResult(), the name of bundle is usuarios os Usuarios ?
If it is useful to anyone, I finally created a non-persistent attribute in the Perfil entity to attach the the relationship and a collection of IPerfil's there:
/**
* #ORM\OneToMany(targetEntity="IPerfil", mappedBy="id")
*/
private $desc;
Need to declare it as a ArrayCollection:
public function __construct()
{
$this->desc = new \Doctrine\Common\Collections\ArrayCollection();
}
And now I'm able to lazy load in the right direction and do any necessary operation. I suppouse Doctrine couldnt load the collection into id, as it wasn't declared as a collection and it's the ID field.

Resources