Symfony3 ManyToMany join - php

I need to get liste of articles who have the id of categorie with join ManyToMany I tried all day but it won't work. with dql query or anything pelase help I am despread.
I want to get liste of articles who have category id with many to many relation
/**
*
* #ORM\ManyToMany(targetEntity="Categorie",mappedBy="cat")
* #ORM\JoinTable(name="article_categorie",
* joinColumns={#ORM\JoinColumn(name="article_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="categorie_id", referencedColumnName="id",onDelete="CASCADE")}
* )
*
*/
private $categorie;
my first try
$qp=$this->createQueryBuilder('p');
$qp->select("p")
->from(Categorie::class,"c")
->where($qp->expr()->eq("c.id","$id"))->setMaxResults(3)
->getQuery()->execute();
return $qp;
my second try
$em = $this->getEntityManager();
$query = $em->createQuery("SELECT article
FROM article t
INNER JOIN article_categorie jt ON(t.id = jt.article_id)
INNER JOIN categorie g ON(g.id = jt.categorie_id)
WHERE_id g.id=9");return $query->getResult();
my third try
$this->createQueryBuilder()
->select('s')
->from('ArticleBundle:Categorie', 's')
->innerJoin('s.Category c ON c.category_id = s.')
->where('s.name = :superCategoryName')
->setParameter('superCategoryName', $superCategoryName)
->getQuery()
->getResult();
Dosn't work

You can try this:
/**
* #ORM\Entity
*/
class Article
{
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Category", cascade={"persist"})
*/
private $categories;
// …
}
and in your repository:
public function getArticlesWithCategories(array $categoryNames)
{
$qb = $this->createQueryBuilder('a');
// We're making a joint with the Category entity with alias "c."
$qb
->innerJoin('a.categories', 'c')
->addSelect('c')
;
// Then we filter on the names of the categories using an IN
//If you really need to take the id, replace the $categorieName variable with $categorieID and "c. name" with "c. id".
$qb->where($qb->expr()->in('c.name', $categoryNames));
// The syntax of the IN and other expressions can be found in the Doctrine documentation
// Finally, we return the result
return $qb
->getQuery()
->getResult()
;
}

Related

createQueryBuilder / Join Column - Symfony

I have a trouble to implement this SQL Request :
SELECT *
FROM project
LEFT JOIN user
ON project.idAuthor=user.id
WHERE project.isVisible = 1 AND
user.role = 'agency'
To a simple Symfony Query Builder :
$query = $this->createQueryBuilder('p')
->leftJoin('WebAwardsBundle:User', 'u')
->where('p.isVisible = 1')
->andwhere("u.role = 'agency'")
->orderBy('p.id', 'DESC')
->getQuery();
The response of this query give me all the project, include the project when role !== agency ...
I don't know where I can put the ON project.idAuthor=user.id
Mapping :
Project :
/**
* Project
*
* #ORM\Table(name="project")
*#ORM\Entity(repositoryClass="WebAwardsBundle\Repostory\ProjectRepository")
*/
class Project
{
...
/**
* #var int
*
* #ORM\ManyToOne(targetEntity="User", inversedBy="projects")
* #ORM\JoinColumn(name="idAuthor", referencedColumnName="id")
*/
private $idAuthor;
...
User :
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="WebAwardsBundle\Repository\UserRepository")
*/
class User implements UserInterface, \Serializable{
...
/**
* #ORM\OneToMany(targetEntity="Project", mappedBy="idAuthor")
*/
private $projects;
...
The correct answer to implement this SQL Request :
SELECT *
FROM project
LEFT JOIN user
ON project.idAuthor=user.id
WHERE project.isVisible = 1 AND
user.role = 'agency'
is to join the correct column of the entity (project.idAuthor to user in this case) :
$query = $this->createQueryBuilder('p')
->join('p.idAuthor', 'u')
->where('p.isVisible = 1')
->andWhere("u.role = 'agency'")
->orderBy('p.id', 'DESC')
->getQuery();

Symfony Doctrine Query For Many to Many Releationships

I have Many to Many relationship between Institutes and Courses. I want to build query that returns only the institutes list whom some courses has been assigned. I have wrote queries in this situation for one to many. but for not many to many. here is the relationships,
class Institutes {
/**
* #ORM\ManyToMany(targetEntity="Courses", inversedBy="institutes")
* #ORM\JoinTable(name="institute_courses",
* joinColumns={#ORM\JoinColumn(name="institute_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="course_id", referencedColumnName="id")}
* )
*/
protected $courses;
}
class Courses {
/**
* #ORM\ManyToMany(targetEntity="Institutes", mappedBy="courses")
*/
protected $institutes;
}
here is the query that i have written, but didn't work properly.
$repository->createQueryBuilder('s')
->leftJoin('CoursesBundle:Courses','c', 'ON c.institutes = s.courses')
->where('s.active = :active')
->andWhere('s.verified = :active')
->setParameter('active', true)
->orderBy('s.name', 'ASC');
This should do the trick:
$repository->createQueryBuilder('i')
->innerJoin('i.courses','c')
->where('i.active = TRUE')
->andWhere('i.verified = TRUE')
->orderBy('i.name', 'ASC');
You can use a JOIN as you would with other kinds of associations. The following query will find all courses which have been assigned at least to one institute:
SELECT c FROM SomeBundle:Courses c JOIN c.institutes i
You can filter the results further by adding a join condition:
SELECT c FROM SomeBundle:Courses c JOIN c.institutes i WITH i.something = :someParam

query builder, one to many where many is empty

I have an entity Category, and this category has a recursive relationship with itself where each category can be a parent to several other categories. The relationship looks like this:
/**
* #var parent
* #ORM\ManyToOne(targetEntity="Category")
* #ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
I need to make a query builder query that selects all categories that are either children(have a parent) Or the categories that have no parent and also have no children (in other words all categories except the parents that have children) I can't seem to be able to do it. Please help.
You need next DQL query:
$query = 'SELECT c FROM AcmeBundle:Category c LEFT JOIN c.parent p LEFT JOIN c.children ch WHERE p IS NOT NULL OR (ch IS NULL AND p IS NULL)';
If you need QueryBuilder sequence for this query you can use next code:
$qb = $em->createQueryBuilder();
$query = $qb
->select('c')
->from('AcmeBundle:Category', 'c')
->leftJoin('c.parent', 'p')
->leftJoin('c.children', 'ch')
->where($qb->expr()->orX(
$qb->expr()->isNotNull('p'),
$qb->expr()->andX(
$qb->expr()->isNull('ch'),
$qb->expr()->isNull('p'),
)
))
->getQuery();

How to JOIN without relational table in Symfony Doctrine with QueryBuilder between 2 entities

I have an Entity Video related with a Entity Category and I need to run this SQL with Doctrine QueryBuilder, with this I can get the most used categories in all videos (1000+):
SELECT c.*
FROM Video v
INNER JOIN video_category vc ON vc.video_id = v.id
INNER JOIN Category c ON vc.category_id = c.id
GROUP BY c.id
HAVING COUNT(v.id) > 1000
ORDER BY c.name ASC;
My querybuilder:
$queryBuilder = $this->getEntityManager()
->createQueryBuilder()
->select('c')
->from('AcmeVideoBundle:Video', 'v')
// Can Doctrine join itself silently with relational info in the Entities?
->join('AcmeCategoryBundle:Category', 'c', Expr\Join::WITH, 'v.id = c.id')
->groupBy('c.id')
->having('COUNT(v.id) > 1000')
->orderBy('c.name', 'ASC')
->getQuery();
But the SQL query output by queryBuilder is this:
SELECT c0_.id AS id0, c0_.NAME AS name1
FROM Video v1_
INNER JOIN Category c0_ ON (v1_.id = c0_.id)
GROUP BY c0_.id
HAVING COUNT(v1_.id) > 1000
ORDER BY c0_.NAME ASC
Without the relational table (video_category)
The Entities mapping:
/**
* Video
*
* #ORM\Table
* #ORM\Entity(repositoryClass="Acme\VideoBundle\Entity\VideoRepository")
*/
class Video
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Acme\CategoryBundle\Entity\Category", cascade={"persist"})
*/
private $category;
// More fields, getters and setters etc...
}
/**
* Category
*
* #ORM\Table
* #ORM\Entity(repositoryClass="Acme\CategoryBundle\Entity\CategoryRepository")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
// More fields, getters and setters etc...
}
How can I use the relation table to run the original SQL query with doctrine Querybuilder? I missed something?
INFO: When I findBy{field}, persist, flush, clear on all entities works fine, the Doctrine relations are ok, I have a Video, Category and video_category tables fine, the original SQL query works perfect.
// Can Doctrine join itself silently with relational info in the Entities?
->join('AcmeCategoryBundle:Category', 'c', Expr\Join::WITH, 'v.id = c.id')
Yes! In fact that is one of the major reasons for using an ORM such as Doctrine 2.
Try:
->leftJoin('v.category','c')
The manual goes into more details though oddly enough is does not seem to have a join example. Hence the common confusion.
http://docs.doctrine-project.org/en/latest/reference/query-builder.html
And you may not be aware of this but the United Nations has passed a resolution outlawing the use of abbreviations for aliases. Just to be safe, try:
$queryBuilder = $this->getEntityManager()
->createQueryBuilder()
->addSelect('category')
->from('AcmeVideoBundle:Video', 'video')
->leftJoin('video.category', 'category')
->groupBy('category.id')
->having('COUNT(video.id) > 1000')
->orderBy('category.name', 'ASC')
->getQuery();
Ok, solved, the problem was that the Entities isn't fully mapped for ManyToMany bidirectional relationship.
The Entities are now:
class Video
{
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Acme\CategoryBundle\Entity\Category", inversedBy="video") // Note the inversedBy key
*/
private $category;
}
class Category
{
/**
* #var Video
*
* #ORM\ManyToMany(targetEntity="Acme\VideoBundle\Entity\Video", mappedBy="category") // Again the inversed
*/
private $video; // New field for bidirectional ManyToMany
}
And the final QueryBuilder working (now with full alias version :P):
$queryBuilder = $this->getEntityManager()
->createQueryBuilder()
->select('category')
->from('AcmeCategoryBundle:Category', 'category')
->join('category.video', 'video')
->groupBy('category.id')
->having('COUNT(video.id) > 1000')
->orderBy('category.name', 'ASC')
->getQuery();
Best regards

Complex Query in Query Builder

How can I execute this query using QueryBuilder in Symfony 2
SELECT um.id, sv.patentgroup_id, pm.portfolio_id, pp.id
FROM sv_patents sv
LEFT JOIN pm_patentgroups pm ON sv.patentgroup_id = pm.id
LEFT JOIN pm_portfolios pp ON pm.portfolio_id = pp.id
LEFT JOIN um_users um ON pp.user_id
The associations in entity classes are defined as
In SvPatents I have
/**
* #var PmPatentgroups
*
* #ORM\ManyToOne(targetEntity="PmPatentgroups")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="patentgroup_id", referencedColumnName="id")
* })
*/
private $patentgroup;
In PmPatentgroups I have
/**
* #var PmPortfolios
*
* #ORM\ManyToOne(targetEntity="PmPortfolios")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="portfolio_id", referencedColumnName="id")
* })
*/
private $portfolio_id;
In PmPortfolios I have
/**
* #var UmUsers
*
* #ORM\ManyToOne(targetEntity="UmUsers")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $user;
I tried this but it is giving me the whole results from the table looks like joins are not working propoerly
$repository = $this->getDoctrine()->getRepository('MunichInnovationGroupBundle:SvPatents');
$qb = $repository->createQueryBuilder('sv')
->leftJoin('sv.patentgroup','pm')
->leftJoin('pm.portfolio_id','pp')
->leftJoin('pp.user','um')
->getQuery();
$patents = $qb->getArrayResult();
I am quite new to Symfony2 and Doctorine2. I read the whole documentation but could not find such complex example actually i am bit confused with how the querybuilder build the query. It would be great if you explain it a little in simple words
Thanks in advance
I found the solution to my problem. If u looks for the records of a specific user in the table then you need to add one where clause. This is how your query should looks like
$user_id = 1;
$repository = $this->getDoctrine()->getRepository('MunichInnovationGroupBundle:SvPatents');
$qb = $repository->createQueryBuilder('sv')
->select('sv')
->leftJoin('sv.patentgroup','pm')
->leftJoin('pm.portfolio_id','pp')
->leftJoin('pp.user','um')
->where('pp.user = :user_id')
->setParameter('user_id', $user_id)
->getQuery();
$patents = $qb->getArrayResult();
Thats all :)
You're very close. You just have to add a ->select() query part:
$repository = $this->getDoctrine()->getRepository('MunichInnovationGroupBundle:SvPatents');
$qb = $repository->createQueryBuilder('sv')
->select('um.id, pm.id, pp.id') // add this part
->leftJoin('sv.patentgroup','pm')
->leftJoin('pm.portfolio_id','pp')
->leftJoin('pp.user','um')
->getQuery();
$patents = $qb->getArrayResult();

Categories