Doctrine query to search entities based on related entity field - symfony

I've ManyToOne relationship in doctrine (Many results to One PollingStation):
/**
* #ORM\ManyToOne(targetEntity="Iballot\CmsBundle\Entity\PollingStation2", inversedBy="results", cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Expose
*/
private $pollingStation2;
I'd like search for all the result that belong to the polling Station that have a name similar to a key word. I try the following method but it does not work:
public function getForSearch($keyWord)
{
$query = $this->_em->createQueryBuilder();
$query
->select('r')
->from('IballotCmsBundle:Result', 'r')
->where($query->expr()->like('p.pollingStation2', $query->expr()->literal('%' . $keyWord . '%')))
//->orderBy('p.', 'ASC')
->getQuery()
->setParameter('keyWord', '%'.$keyWord.'%');
return $query->getQuery()->getResult();
}
I get the following error
[Semantical Error] line 0, col 48 near 'pollingStation2': Error:
Invalid PathExpression. Must be a StateFieldPathExpression.

As said by #Cerad (one more time), you need a JOIN to make the associated entity available while building your query.
Try this :
$query = $this->_em->createQueryBuilder();
$query
->select('r')
->from('IballotCmsBundle:Result', 'r')
->leftJoin('r.pollingStation2', 'p') // The missing join
->where('p.name LIKE :keyword') // where p.name like %keyword%
->setParameter('keyword', '%'.$keyword.'%')
->orderBy('p.name', 'ASC') // order by p.name ASC
->getQuery()
return $query->getResult();
BTW I fixed your orderBy, simplified your where and fixed the keyword parameter that is wrongly defined.

Try putting this method in your Result EntityRepository class:
public function getForSearch($keyWord)
{
$query = $this->createQueryBuilder('r');
$query
->join('r.pollingStation2', 'p')
->where('p.name LIKE :keyword')
->setParameter('keyword', '%' . $keyWord . '%')
//->orderBy('p.', 'ASC')
;
return $query->getQuery()->getResult();
}

Related

What is wrong with this Doctrine querying on ManyToMany relation

I am trying Symfony 4 and I can't get this query right. The same thing worked OK in Symfony 3. I have 2 entities. One is a person and the other is a day. The relation is ManyToMany. I would like to get all days for a specific person
I tried using MEMBER OF and joining tables, but nothing works for this example.
// Day entity
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Person", inversedBy="days")
*/
private $person;
// Person entity
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Day", mappedBy="person")
*/
private $days;
// Repository function
return $this->createQueryBuilder('d')
->andWhere('d.person = :person')
->setParameter('person', $person)
->getQuery()
->getResult()
;
This is the error I get:
In QueryException.php line 65: [Semantical Error] line 0, col 58 near
'person = :pe': Error: Invalid PathExpression.
StateFieldPathExpression or SingleValuedAssociationField expected.
In QueryException.php line 43:
SELECT d FROM App\Entity\Day d WHERE d.date = :date AND d.person =
:person
The issue is not about Symfony version it's about orm version, i guess
So you could try this by using IDENTITY
return $this->createQueryBuilder('d')
->andWhere('IDENTITY(d.person) = :person')
->setParameter('person', $person)
->getQuery()
->getResult()
;
or
return $this->createQueryBuilder('d')
->leftJoin('d.person', 'p')
->andWhere('p.id = :person')
->setParameter('person', $person)
->getQuery()
->getResult()
;
You can get person related days just from association like $person->getDays()

DQL query ManyToMany IN

This query in not working. What could be wrong? Post has author(User entity). User has Following(ManyToMany self-directing)
I'm trying to get all Posts of the Users which I'm following
$userId = $this->getUser()->getId();
$qb = $em->createQueryBuilder();
$qb2 = $qb;
$qb2 = $em->createQueryBuilder()
->select('u.following')
->from('AppBundle\Entity\User', 'u')
->where('u.id = :userId');
$qb->select('p')
->from('AppBundle\Entity\Post', 'p')
->where($qb->expr()->In('p.author', $qb2->getDQL()));
$qb->setParameter('userId', $userId);
$dql = $qb->getDQL();
I will assume that your code is in repository as it should be...
src/AppBundle/Controller/PostController.php
$em=$this->getDoctrine()->getManager();
$myResultCollection=$em->getRepository(Post::class)->myCustomQuery($this->getUser());
src/AppBundle/Repository/PostRepository.php
public function myCustomQuery(User $user) {
$em=$this->getEntityManager();
$qb=$em->createQueryBuilder();
return $qb->select("p")
->from(Post::class, "p")
->where($qb->expr()->in("p.author",
$qb->select("u.following")
->from(User::class, "u")
->where("u.id=:USERID")
->getDQL()))
->setParameters(array('USERID'=>$user->getId()))
->getQuery()
->execute();
}
As side note, you should be careful with quotes.
Make sure to use double quotes when using DQL (it's true for SQL too).
The reason is because you need simple quote for strings in queries.

Order by innerJoin table with doctrine

I have a OneToMany relationship between two entities: Shop and Comment. I would like to display a list of Shops ordered by the date of the last review they received.
This is what I tried so far:
return $this->createQueryBuilder('s')
->innerJoin('s.reviews', 'r', 'WITH', 'r.shop = s.id')
->orderBy('r.createdAt') // <- that does nothing on the order of the shops
->getQuery()
->getResult();
This returns all the shops, but they aren't ordered at all...
Try to set OrderBy directly on your #ORM\OneToMany mappedBy relation like this:
/**
* #ORM\OneToMany...
* #ORM\OrderBy({"createdAt" = "DESC"})
*/
private $reviews;
If you want to use it inside your ShopRepository you should try it this way
return $this->getEntityManager()
->createQueryBuilder()
->select('s, MAX(r.createdAt) AS maxCreatedAt')
->from('AppBundle:Comment', 'r')
->join('AppBundle:Shop', 's', 'WITH', 'r.shop = s.id')
->groupBy('s')
->orderBy('maxCreatedAt', 'DESC')
->getQuery()
->getResult();
Don't forget to modify the bundle namespaces (AppBundle) accordingly.

Key "productTitle" for array with keys "0, catTitle" does not exist in EagleShopBundle:global:product.html.twig

I'm trying to join two tables and print a value in twig template but I'm having this issue.
This is my Controller action.
/**
* #Route("products/display/{id}")
* #Template()
*/
public function displayAction($id) {
$em = $this->container->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('p, pc.catTitle')
->from('EagleShopBundle:Products', 'p')
->leftJoin('EagleShopBundle:ProductCategory', 'pc', \Doctrine\ORM\Query\Expr\Join::WITH, 'pc.id = p.category')
->where($qb->expr()->eq('p.id', '?5'))
->setParameter(5, $id);
$product = $qb->getQuery()->getOneOrNullResult();
return $this->render("EagleShopBundle:global:product.html.twig", array(
'product' => $product,
'image_path' => '/bundles/eagleshop/images/'
));
}
This is my twig file line related to the issue,
<h1>{{product.productTitle}}</h1>
I guess issue is related to this line
$qb->select('p, pc.catTitle')
This is the error I get,
Key "productTitle" for array with keys "0, catTitle" does not exist in
EagleShopBundle:global:product.html.twig
You could try next query:
$qb->select('p, partial pc.{id, catTitle}')
// if you need full productCategory object then write just 'p, pc'
->from('EagleShopBundle:Products', 'p')
->leftJoin('p.category', 'pc')
//productCategory is the field
//in product entity which has relation to product category entity,
//paste your field (not column!) name here
//if it is not productCategory
->where('p.id = :productId')
->setParameter('productId', $id);
P.S.
It is better to move queries to entity repositories :)
P.P.S.
Doctrine partial objects
UPD
Fixed query - with right field name

Use Limit and Offset in Doctrine2 query

I'm trying to do the pagination, but there is an error:
[Syntax Error] line 0, col 57: Error: Expected end of string, got 'limit'
I'm not quite sure if this is the right syntax (and logic) to make my query:
public function getFriendsFromTo ($user, $limit, $offset)
{
return $this->getEntityManager()
->createQuery('SELECT f FROM EMMyFriendsBundle:Friend f WHERE f.user='.$user.' limit '.$limit. 'offset' .$offset)
->getResult();
}
Friends and users are related manyToOne and oneToMany, so in the friends table there is a field - user_id.
This is in my controller:
$user = $this->get('security.context')->getToken()->getUser();
$id = $user->getId();
$friends = $user->getFriends();
$result = count($friends)
$FR_PER_PAGE = 7;
$pages = $result/$FR_PER_PAGE;
$em = $this->getDoctrine()->getEntityManager();
$friends = $em->getRepository('EMMyFriendsBundle:Friend')
->getFriendsFromTo($id, $FR_PER_PAGE, $page*$FR_PER_PAGE);
I know that it's stupid and even wrong (especially the third parameter to be $page*$FR_PER_PAGE), but I just wanted to try if the query works, and it didn't.
Nope. Use:
return $this->getEntityManager()
->createQuery('...')
->setMaxResults(5)
->setFirstResult(10)
->getResult();
$towary = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Towar')
->findBy(array(),array(),10,($current-1)*$numItemsPerPage);
You can use findBy 3rd and 4th parameters of method of doctrine repository, which are limit and offset.
Here is the method definition:
findBy(
array $criteria,
array $orderBy = null,
integer|null $limit = null,
integer|null $offset = null
)
Source: http://www.doctrine-project.org/api/orm/2.2/class-Doctrine.ORM.EntityRepository.html
you can also use
$query->getSingleResult();
Doctrine2.6, stumbled upon this old post and tried the DQL way but it did not fit for purpose. So if you want to avoid using DQL because you already have Entities mapped and joined together, you can do paging using matching & Criteria
$criteria = Criteria::create()
->setMaxResults($limit ? $limit : null)
->setFirstResult($offset ? $offset : null)
$result = $em->getRepository('EMMyFriendsBundle:Friend')
->matching($criteria)->toArray();

Resources