Doctrine sort by 2 different entities - symfony

I'm building a forum with Symfony and I'm currently wondering on how I'm about to list the latest activity using Doctrine.
I have a OneToMany relationship between Topic & Post.
I'd have to check for the latest things happened, which might be a post on a topic, or a topic itself.
How would you guys do this as clean as possible?
I would probably UNION both somehow sort by date and select last 5.
Thank you in advance!

You can try something like this (It's a function of repository post) :
public function lastTopics(){
// Build query
$qb = $this
->createQueryBuilder('p')
->select('p')
->leftJoin('p.topic', 't')
->addSelect('t')
->addGroupBy('p.id')
->addGroupBy('t.id')
->orderBy('p.dateCreation', 'DESC')
->setMaxResults(5)
;
// Get query
$query = $qb->getQuery();
// Return results
return $query->getResult();
}
Then just list the last 5 posts by viewing topics. Enjoy ;)

Related

Access entity methods with getArrayResult

I'm experiencing performance issues and I'm trying to retrieve hydrate array with return $qb->getQuery()->getArrayResult(); from my repository to improve it.
The performance is slightly better, but I can't access my custom entity methods anymore... I guess it's a normal behavior, but is there a way to go through it ?
EDIT:
Loading time of my controller is way to long on my local dev environment
My controller action is only retrieving a set of objects from my repository, here is the code :
public function findAllForAdmin()
{
$qb = $this
->createQueryBuilder('a')
->leftJoin('a.subcategory', 's')
->addSelect('s')
->leftJoin('s.category', 'c')
->addSelect('c')
->leftJoin('a.user', 'u')
->addSelect('u')
->leftJoin('a.advertpaidoptions', 'apo')
->addSelect('apo')
->leftJoin('a.photos', 'p')
->addSelect('p')
;
return $qb
->getQuery()
->getArrayResult()
;
}
a is for advert, I'm retrieving about 2k adverts. That's not so much IMO...
I don't know where to look...
getArrayResult will return result of select into an array, so it's not possibile anymore to have back your entities.
If you need to fetch all (or certain) infos of the entity, you can follow to strategies:
Implicit (at query builder level) make them part of select builder's part
Use fetch=EAGER on entity attribute
Well, I think I managed to improve my performance issue, the answer seems to be pretty obvious though...
Instead of loading the whole entities, I just load the fields I need...
public function findAllForAdmin()
{
$qb = $this
->createQueryBuilder('a')
->select(array(
'a.id',
'a.dateCreate',
'a.title',
'a.price',
'a.price_type',
'a.completed',
'a.deleted',
'a.slug',
))
->leftJoin('a.subcategory', 's')
->addSelect('s.slug AS s_slug')
->leftJoin('s.category', 'c')
->addSelect('c.slug AS c_slug')
->leftJoin('a.user', 'u')
->addSelect('u.username')
->leftJoin('a.advertpaidoptions', 'apo')
->addSelect('COUNT(apo.id) AS nb_apo')
->leftJoin('a.photos', 'p')
->addSelect('COUNT(p.id) AS nb_p')
->groupBy('a.id')
;
return $qb
->getQuery()
->getResult()
;
}
The improvement is huge...

Method findBy() from Doctrine with DateTime

I have the following code, but this would not work:
$event= $this->getDoctrine()
->getRepository('AppBundle:Event')
->findBy(
array(
"datestart" => array(new \DateTime())
)
);
I need a list of the events, which are newer then now.
Where is my misstake?
Or isn't that able to get with the default findBy() function of doctrine ?
findBy only search for exactly matches while you need greater then. In this case and also many other cases you can write your own query. You could use DQL or the queryBuilder. If you want to be able to re-use your query on other places then you could place your query in a repository class which is a good practice too. (check the docs). Now here you find a DQL example that you can place into your controller:
$events = $this->getDoctrine()
->getManager()
->createQuery('SELECT e FROM AppBundle:Event e WHERE e.datestart > CURRENT_DATE()')
->getResult();
i changed your variabele to $events (with s) because you are expecting possible more than one event.

Symfony2 - Query Builder multiple orderBy

I have the following code
public function queryAssociationsSorted($id){
$qb = $this->createQueryBuilder('a')
->leftJoin('a.category', 'c')
->where('a.job = :id')
->setParameter('id', $id)
//->addOrderBy('c.rank', 'DESC')
//->addOrderBy('a.updated', 'DESC')
->add('orderBy','c.rank DESC THEN a.updated DESC')
;
return $query = $qb->getQuery();
}
and this or the commented out options both only sort by a.updated. I have looked at other posts on this subject and can't find a solution. Can anyone suggest where I am going wrong?
If I understand correctly, and this is the result yu want:
id - rank - updated
xx - 4 - 2014-01-01
xx - 3 - 2014-01-02
xx - 3 - 2014-01-01
This actually works:
$qb = $this->createQueryBuilder('a')
->leftJoin('a.category', 'c')
->where('a.job = :id')
->setParameter('id', $id)
->addOrderBy('c.rank', 'DESC')
->addOrderBy('a.updated', 'DESC')
;
return $query = $qb->getQuery();
I'm not sure how doctrine works with multiple sort by..
why dont you try to use dql or even raw sql query?
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html
http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html
Edit:
something like that will work I think:
->add('orderBy','c.rank DESC, a.updated DESC')
If you still have no success the raw sql query will save you ;)
Over a year later and I've stumbled across the correct answer in this answer by #red777
This will help you:
$adapter = new DoctrineORMAdapter($queryBuilder, false);
Had the same problem this morning. By default Pagerfanta is treating your query as
one with joins. Setting second argument to false makes it use simple
query handling.
In Kunstmaan Bundle, in AdminListConfiguration class, you have to
overide function that is creating Pagerfanta, if you want to sort
simple entity.
The syntax in the query had always been correct, but the error crept in in the DoctrineOrmAdapter. Adding false as the second parameter sorted the problem

Doctrine Querybuilder issues in symfony2. Usage questions

Using doctrine for the first time in a project, and I'm having a few issues with the query builder.
First up, in a controller I used the following:
$conn = $this->get('database_connection');
$users = $conn->fetchAll('SELECT * FROM Users');
This worked fine and returns an array of users from my DB.
I then tried to use the query builder to fetch the forenames of all users. By looking at examples i found the following:
$conn = $this->get('database_connection');
$qb = $conn->createQueryBuilder();
$qb->select("forename")
->from("Users", "u")
->where("u.id = :user_id")
->setParameter('user_id', 1);
$query = $qb->getQuery();
$results = $query->getResults();
I get told that the gDoctrine\DBAL\Query\QueryBuilder::getQuery() method is not defined, which I found odd as almost all the examples I found use it.
I did a search and found Doctrine documentation but I'm now confused how to use it at all.
Would someone be kind enough to give me an example of how to use the above to retrieve the forename for the User with id 1. I'm sure that once I have a simple example that work I will be fine from there.
Thanks!
Now Resolved:
After looking at the Documentation (and with help from others), I found the general layout for the queryBuilder is as follows:
$conn = $this->get('database_connection');
$qb = $conn->createQueryBuilder();
$stmt = $qb->select("forename")
->from("Users", "u")
->where("u.id = :user_id")
->setParameter('user_id', 1)
->execute();
$userNames = $stmt->fetchAll();
The general idea being that the execute method returns a Doctrine\DBAL\Driver\Statement, with the parameters set as specified. From this statement you can call one of the various method stated here to get the results from the DB.
Hope this helps someone else who is having problems!
I think you might be confused slightly by the documents on doctrine and using it with symfony. From the error message you are getting a DBAL\Query\QueryBuilder. There is not a method getQuery for that object. You should be able to use the execute method to get the results you want.
Now with that being said the way I would do it is through either a repository class for the Users entity, or I would do
$em = $this->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
then do what you were doing before...

How to list user based on their roles in Symfony2 + Doctrine effectively

I have done this with this code
$users = $this->getDoctrine()->getEntityManager()
->createQuery('SELECT tu FROM UserBundle:User tu')
->getResult();
$result = array();
foreach($users as $user){
if($user->hasRole('ROLE_CUSTOMER'))
$result[] = $user;
}
return $this->render('XBundle:Order:index.html.twig',
array('users' => $result));
But what is the simple way to achieve this same result ?
Thanks.
Update, additional info:
Our main problem is that user roles have a hierarchical structure.
So ROLE_EDITOR will automatically have ROLE_WRITER if I defined ROLE_WRITER under ROLE_EDITOR.
Thus I can't just use simple query, I think I also have to utilize security context component.
I don't know your schema, but I guess you could do an INNER JOIN and put your condition in the ON clause. Read this article about the query builder to figure out how to build your query.
Doctrine collections also have a filter method that takes a Closure as an argument.

Resources