Symfony Many-to-many query - symfony

I have a question about Symfony's Many-to-many relationships. I have a query, that tries to get all the fields of an entity (outside this part), and on top of that query, it adds the following:
$queryBuilder
->leftJoin('AppBundle:Location', 'location',
Join::WITH, 'location.id IN (entity.locations)')
->andWhere('location.institute=:institute')
->setParameter('institute', $user->getInstitute());
On that entity, a Many-to-many relationship is present: entity has a m2m relationship with location. Now I try to get all entities that have the same institute as the user has.
So I query the locations, and check if the institute of the locations have the same institute.
However, I then get
[Syntax Error] line 0, col 118: Error: Expected Literal, got 'entity'
What should I be doing different? I understand it goes wrong with the IN part of the query.

I think your entity.locations is a variable.
If so, you need to add : in front of and setParameter as well.
Change your code to:
$queryBuilder
->leftJoin('AppBundle:Location', 'location', Join::WITH, 'location.id IN (:locations)')
->setParameter('locations', entity.locations);
->andWhere('location.institute=:institute')
->setParameter('institute', $user->getInstitute());
Please let me know if this solve your issue, thanks!

In the end, I found out that the answer is as follows:
$queryBuilder
->leftJoin('AppBundle:Location', 'location',
Join::WITH, 'location MEMBER OF entity.locations')
->andWhere('location.institute=:institute')
->setParameter('institute', $user->getInstitute());

Related

Doctrine get non null ArrayCollection

I would like to get all Entity only if the parameter is part in this entity or if the entity parameter is empty.
I have this:
$qb = $this->createQueryBuilder('cc')
->join('Toblor\Entity\Paramount', 'p')
->select('p')
->Where(':company MEMBER OF p.company_activated')
->setParameter('company ', $company)
return $qb->getQuery()->getResult();
And it is doing to job great. But now I would like to have the same result if company is a part of company_actived OR if company_activated is empty. I have tried an
->Where('(:company MEMBER OF p.company_activated OR p.company_activated IS NULL)')
It trigger me this error
Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.
Is there an easy way to do this thing ? Because I need to implement on a lot of fields.
Thanks you
Is your relation with company_activated ManyToMany or OneToMany.
If it's the case, you need to add:
->leftJoin('p.company_activated', 'ca')
then check if ca IS NULL

link between QueryBuilder parameters

public function Bycategorie($categorie)
{
$qb = $this->createQueryBuilder('u')
->select('u')
->where('u.categorie = :categorie')
->orderBy('u.id')
->setParameter('categorie',$categorie);
return $qb->getQuery()->getResult();
}
I want to know what the link is between:
$categorie, u and the entity in which I'm working,
Your question is related to Doctrine. About association mapping you can read here
In your example relation can be One-to-One (in theory) or Many-to-One (many users can obtain the same category). Many-to-One relation is more preferable variant and has a logical explanation.
helo, i have found what i was searching for.
my question was : what is the link between querybuilder parameters.
in my example i find that in the where clause (where('u.categorie =:categorie'))
'categorie' of the left(in the parenthesis) must be a colum of a table in my database.
thanks for your helps.

Cannot select entity through identification variables without choosing at least one root entity alias

Ads entity is described by geographic information: Country> Region>County. The Ads entity is only linked with County. Consequently, retrieving Ads by countries will require us joining entities twice.
My goal is counting the number of Ads for a given country. For that, I tried this DQL query but without success:
public function getMotorsAdsCountByCountry($slug){
$qb = $this->_em->createQueryBuilder()
->select("m.id, COUNT(m.id) AS cnt")
->from("MinnAdsBundle:MotorsAds", "m")
->join("m.county","county")->addSelect("county")
->join("county.region","region")->addSelect("region")
->join("region.country","country")->addSelect("country")
->where("country.slug=:slug")
->setParameter(":slug", $slug);
return $qb->getQuery()->getSingleScalarResult();
}
The error I got is:
[Semantical Error] line 0, col -1 near 'SELECT m.id,': Error: Cannot
select entity through identification variables without choosing at
least one root entity alias.
I have even seen a post regarding the same error in this link but without success.
I found the solution:
$qb = $this->_em->createQueryBuilder()
->select("COUNT(m.id) AS cnt")
->from("MinnAdsBundle:MotorsAds", "m")
->join("m.county","county")
->join("county.region","region")
->join("region.country","country")
->where("country.slug=:slug")
->setParameter(":slug", $slug);
I have just remove the addSelect() in addition to the modification of the select().
try changing
->select("m.id, COUNT(m.id) AS cnt")
to
->select("m, COUNT(m.id) AS cnt")
or change hydration to array
this is known as Doctrine limitation you should first join with MotorAds Entity like this
from('MinnAdsBundle','mi')->leftJoin(MotorsAds::class,'m','WITH','mi.motorsAds = m');
then you can select form MotorsAds directly
refer to this answer

Symfony2 QueryBuilder join ON and WITH difference

I'm new with Symfony2 and I built successfully my first join through QueryBuilder and Doctrine 2.
Probably this is a stupid question but both on-line and in the Symfony2's methods I was unable to find anything for understanding the difference between the join clauses "WITH" and "ON".
For example this is my join code:
->leftJoin('EcommerceProductBundle:ProductData', 'pdata', 'WITH', 'prod.id = IDENTITY(pdata.product)')
It works good but if I put ON instead of WITH I get the following error:
[Syntax Error] line 0, col 200: Error: Expected
Doctrine\ORM\Query\Lexer::T_WITH, got 'ON'
Why? I've seen among the objects that there are both the T_ON and T_WITH like join clauses, but which is their usage difference? What is their uses like?
#florian gave you the correct answer but let me try to explain it on example:
In sql, joins are done like this:
SELECT * FROM category
LEFT JOIN product ON product.category_id = category.id
(or something like this)
Now in Doctrine, you don't need to use ON clause because doctrine knows that from relations annotations in your entities. So above example would be:
// CategoryRepository.php
public function getCategoriesAndJoinProducts()
{
return $this->createQueryBuilder("o")
->leftJoin("o.products", "p")->addSelect("p")
->getQuery()->getResult() ;
}
Both would fetch all categories and join products associated with them.
Now comes the WITH clause. If you want to join only products with price bigger than 50, you would do this in SQL:
SELECT * FROM category
LEFT JOIN product ON product.category_id = category.id AND product.price>50
In Doctrine:
// CategoryRepository.php
public function getCategoriesAndJoinProductsWithPriceBiggerThan($price)
{
return $this->createQueryBuilder("o")
->leftJoin("o.products", "p", "WITH", "p.price>:price")
->setParameter("price", price)->addSelect("p")
->getQuery()->getResult() ;
}
So, in reality you should never, ever use ON if you are using Doctrine. If you have a need for something like that, you can be almost sure that you screwed something else.
In theory, ON permits you to give the full join criterias, while WITH permits to add additional criterias to the default ones (IMHO).
But, what DQL permits is to avoid giving the JOIN criterias:
You just have to say: $qb->leftJoin('prod.pdata', 'pdata');
And doctrine2 will handle the join correctly.
Here is a related question about that: Can I use "ON" keyword in DQL or do I need to use Native Query?

Doctrine2 innerJoin between two tables without association defined

I'm trying to join a table that has no association defined in my config file. Why? Because I don't want to pollute this entity (Section) because many other entity can be related to this one with a "Many to One" relation. So, I define the relation only on one side, so it doesn't pollute my Section entity.
What I'm trying to do is :
// Find all sections with this bundle linked
$query = $this->getEntityManager()->getRepository('CompanyBackendSectionBundle:Section')->createQueryBuilder('s')
->select('s', 'st')
->innerJoin('s.translations', 'st')
->innerJoin('s.sectionBundles', 'sb')
->innerJoin('Company\Backend\FaqBundle\Entity\FaqQuestion', 'fq')
->where('st.locale = :locale')
->andWhere('sb.bundle = :bundleId')
->orderBy('st.name')
->setParameters(array(
'locale' => $this->getLocale(),
'bundleId' => $bundle->getId()
));
The problem is with "->innerJoin('Company\Backend\FaqBundle\Entity\FaqQuestion', 'fq')", I got :
[Semantical Error] line 0, col 179 near 'fq WHERE st.locale': Error: Identification Variable Company\Backend\FaqBundle\Entity\FaqQuestion used in join path expression but was not defined before.
Is there a way to do it other than using Doctrine Native Query?
No. Doctrine Query Language needs you to define the relation in the direction you wanna use it...

Resources