Symfony 2 & Doctrine 2 - create a custom findBy() method - php

I would like create my own method findBy().
I have two entities: Film and Genre. The purpose of this custom findBy() method is :
join the Film entity with the Genre entity, to retrieve all my films
and the associated genres,
keeping the parameters of the basic method which are: $criteria,
$orderBy , $limit and $offset.
Indeed, I use those parameters to make a paging.
Previously I made a custom findAll method with the join between the two entities :
<?php
public function myFindAll()
{
$films = $this->createQueryBuilder('f')
// leftJoin because I need all the genre
->leftJoin('f.genres', 'g')
->addSelect('g.label')
->groupBy('f.id')
->getQuery()
->getArrayResult();
// $genres contains all the genres and the associated movies
return ($films);
}
I don't know how to include the rest of parameters.

How about slice() ?
$genders = $em->getRepository('models\Gender')->findAll()->slice($offset, $lenght);
Also, you can make use of your function like:
public function myFindAll($criteria, $orderBy, $limit, $offset)
{
$films = $this->createQueryBuilder('f')
// leftJoin because I need all the genre
->leftJoin('f.genres', 'g')
->addSelect('g.label')
->groupBy('f.id')
->add('orderBy', "f.{$orderBy} ASC")
->getQuery()
->getArrayResult()
->slice($offset, $limit);
// $films contains all the genres and the associated movies
return ($films);
}
EDIT:
The slice() function acts as pagination function:
$page1 = $films->slice(0, 15); // retrieve films from 0 to 15 position
$page2 = $films->slice(10, 7); // retrieve films from 10 to 17 position
Now, if you want to use some criterias values you can make something like this:
public function myFindAll($criteria, $orderBy, $limit, $offset)
{
$films = $this->createQueryBuilder('f');
foreach($criteria as $column => $value)
$films->where($column, $value);
$films
->leftJoin('f.genres', 'g')
->addSelect('g.label')
->groupBy('f.id')
->add('orderBy', "{$orderBy[0]} {$orderBy[1]}");
->getQuery()
->getArrayResult()
->slice($offset, $limit);
// $genres contains all the genres and the associated movies
return ($films);
}
I am not sure if where function will override the previous conditions, but at least it can lead you to find the correct query
setFirstResult() and setMaxResult()
Also, there is another option that you can use:
public function myFindAll($criteria, $orderBy, $limit, $offset)
{
$films = $this->createQueryBuilder('f');
foreach($criteria as $column => $value)
$films->where($column, $value);
$films
->leftJoin('f.genres', 'g')
->addSelect('g.label')
->groupBy('f.id')
->add('orderBy', "f.{$orderBy[0]} {$orderBy[1]}")
->setFirstResult($offset)
->setMaxResults($limit)
->getQuery()
->getArrayResult();
// $genres contains all the genres and the associated movies
return ($films);
}

Related

Symfony Query Builder (Many to many relation)

I have question about QueryBuilder.
I have two entities: Product, Attribute, which are in many to many relations (Each Product can have many attributes, and each attribudes can have many products)
I create product repository function findByAttributes()
public function findByAttributes($attributes)
{
$qb = $this->createQueryBuilder('p')
->join('p.attributes', 'a')
->where('a.slug = :slug1 OR a.slug = :slug2')
->setParameter('slug1', 'red')
->setParameter('slug2', 'blue')
;
return $qb->getQuery()->getResult();
}
When i use OR it work fine, but when i switch to AND result is empty.
With AND I want to select only products who have both attributes.
Where I am wrong?
Tnx
I got it!
public function findByAttributes(array $attributes)
{
$qb = $this->createQueryBuilder('p');
foreach ($attributes as $i => $attribute) {
$qb->join('p.attributes', 'a'.$i)
->andWhere('a'.$i.'.slug = :slug'.$i.'')
->setParameter('slug'.$i, $attribute);
}
return $qb->getQuery()->getResult();
}

Find element in array data using createQueryBuilder

I have a table ( shops) in witch I store data like this: ["bsd1234","qwe9876"] in a field named products and I want to get the shops objects that contain a given product using createQueryBuilder().
It should look like this, but I can't find the solution:
public function findByProducts($value)
{
return $this->createQueryBuilder('s')
->andWhere('s.products = :val')
->setParameter('val', $value)
->orderBy('s.id', 'ASC')
->getQuery()
->getResult()
;
}
Can you help mw with that?

How to get related items in controller (Symfony2.8)

For this question I have 3 entities in my DB :
Case to Line : 1 Case to Many Lines (1 case have n lines)
Line to Loan : 1 Line to Many Loans (1 line have n loans)
I want in my controller to get a Case(Dosier) by ID, then to foreach lines, and then to foreach every loan.
So, with every loan object I want to perform some calculations and collect all this data.
How can I access the loan object, to make next things like ($loan->getCapital(), $loan->getDuration() for my calculations?
I tried in this way :
/**
* #Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
$user = $this->getUser();
$dosiers = $this->getDoctrine()
->getRepository('AppBundle:Dosier')
->createQueryBuilder('e')
->select('e')
->where('e.userId = :id')
->andwhere('e.isActive = 1')
->orderBy('e.id', 'DESC')
->setParameters(array('id'=> $user))
->getQuery()
->getResult();
foreach ($line as $dosiers->getLines()) {
foreach ($loan as $line->getLoans()) {
echo $loan->getName();
}
}
return $this->render('AppBundle:default:index.html.twig', array(
'dosiers' => $dosiers
));
}//indexAction
But it gives me error :
Compile Error: Can't use method return value in write context
Ah, I find a solution :
This code :
$dosiers = $this->getDoctrine()
->getRepository('AppBundle:Dosier')
->createQueryBuilder('e')
->select('e')
->where('e.userId = :id')
->andwhere('e.isActive = 1')
->orderBy('e.id', 'DESC')
->setParameters(array('id'=> $user))
->getQuery()
->getResult();
returns an array of objects that match that conditions, instead returning one object.
So, I changed the query for test in :
$dosiers = $em->getRepository('AppBundle:Dosier')->findOneBy(array('id' => 15));
and the loop to :
foreach ($dosiers->getLines() as $line) {
foreach ($line->getLoans() as $loan) {
echo $loan->getName();
}
}
and now it works. Next, need just to add a new parameter to the action, $id, and instead of constant '15' in query to put $id.

multiple counts on an object in a doctrine 2 query

I am trying to do multiple counts on an entity in a doctrine 2 query.
I am able to get the count correctly when I do a single count but run into problems when I do multiple counts in the same query.
Also, my query returns the entity; but I don't want the entity. I just want the counts.
This is my query;
public function getMessagesCount()
{
$qb = $this->queryBuilder();
$qb->select(array('u','count(fa)as favouritesAdded','count(se)as sentMessages' ))
->from('BaseModel\Entity\User','u')
->leftJoin('u.theFavouriteAdded', 'fa')
->leftJoin('u.sentMessagesObject', 'se')
->where('u.id = :identifier')
->setParameter('identifier',(int)$this->getUserId());
$query = $qb->getQuery();
return $data = $query->getArrayResult();
}
This query returns the same numbers for both counts (i.e both incorrectly returned a count of 20 each)
However, when I did just a single count for each; they query returned the correct account each time. i.e;
public function getMessagesCounts()
{
$qb = $this->queryBuilder();
$qb->select(array('u','count(fa)as favouritesAdded' ))
->from('BaseModel\Entity\User','u')
->leftJoin('u.theFavouriteAdded', 'fa')
// ->leftJoin('u.sentMessagesObject', 'se')
->where('u.id = :identifier')
->setParameter('identifier',(int)$this->getUserId());
$query = $qb->getQuery();
return $data = $query->getArrayResult();
}
I tried adding a group by to the query; but it still returned the incorrect numbers.i.e
->groupBy("u.favouritesAdded","u.sentMessages")
What is the correct way to do a multiple count on a query?
For single count:
(returns count without returning entities)
public function getMessagesCounts()
{
$qb = $this->queryBuilder();
$qb->select('count(se)')
->from('BaseModel\Entity\User','u')
->leftJoin('u.sentMessagesObject', 'se')
->where('u.id = :identifier')
->setParameter('identifier', (int) $this->getUserId());
return $qb->$query->getResult();
}
For two in one count:
public function getMessagesCounts()
{
$qb = $this->queryBuilder();
$qb->select('count(fa), count(se)')
->from('BaseModel\Entity\User','u')
->leftJoin('u.theFavouriteAdded', 'fa')
->leftJoin('u.sentMessagesObject', 'se')
->where('u.id = :identifier')
->setParameter('identifier', (int) $this->getUserId());
return $qb->$query->getResult();
}

How to look for items in an arraycollection from a innerJoined entity in dql?

I want to select visits form users. The visits should contain tag names that are occuring in an array I am passing to dql.
Till now this is what I have:
// select the user database
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select('u')
->from('MyBundle:User', 'u');
->innerJoin('u.visits', 'v');
->innerJoin('v.tags', 't');
Now I want to look for visits that have tags ('t') with names i.e. 'VIP' AND 'Employee' AND ... etc. These names are dynamic, the array could be any length .
't' has a property name and is an arraycollection from 'v'
'v' is an arraycollection form 'u'
How do I do this?
Thank you.
You should use a WHERE IN statement, passing as the parameter the array of names.
$qb->add('where', $qb->expr()->in('t.name', array('VIP', 'Employee', '...')));
i solved through recursion
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select('u')
->from('MyBundle:User', 'u');
$qb ->innerJoin('u.visits', 'v');
$qb->andWhere($qb->expr()->in('v.id', $this->getVisitDQL($qb, $visitData, $tagCounter)));
public function getVisitDQL(QueryBuilder $qb, $data, $counter) {
$tag = $data['tags'][$counter];
$tagName = $tag['content'];
$qb2 = $this->getEntityManager()->createQueryBuilder();
$qb2
->select('v'.$counter.'.id')
->from('MyBundle:Visit', 'v'.$counter)
->innerJoin('v'.$counter.'.tags', 'vt'.$counter)
->where($qb2->expr()->eq('vt'.$counter.'.name',':vtag_'.$counter ));
$qb->setParameter(':vtag_'.$counter, $tagName);
// if were not processing the last filter, continue recursion
if ($counter != (count($data['tags'])-1)) {
$qb2->andWhere($qb->expr()->in('v'.$counter.'.id', $this->getVisitDQL($qb, $data, $counter + 1)));
}
return $qb2->getDQL();
}

Categories