phpormdoctrinenette

Doctrine: How to order by attribute from association with Criteria


I am not able to order records by attribute from another entity.

I have class Employee, which has attribute $user, which points to class User, which have attribute $active.

Now I want to sort Employee by user.active and I am not able to do that. This is how I call the em:

/**
* @param Criteria $criteria
* @param array $order_by
* @param integer $limit
* @param integer $offset
* @return \Doctrine\Common\Collections\Collection
*/
public function findByCriteria($criteria, $order_by = null, $limit = null, $offset = null) {
  $criteria->setFirstResult($offset);
  $criteria->setMaxResults($limit);
  $criteria->orderBy($order_by);

  $result = $this->repository->matching($criteria);

  return $result;
}

I inspected BaseEntityPersister.php and it seems like there is no implementation of such a thing. It just checks if user.active is an attribute of Employee class and throws

Doctrine\ORM\ORMException

Unrecognized field: user.active

I know I can do that via QueryBuilder and joins, but I want to make my code more reusable and Criteria seemed like a good choice.

Thank you for your advices!

EDIT:

If I use findBy, there is no problem with sorting field user.active. Should I consider this a limitation of matching method? It is sad, because I need to use Doctrine\Common\Collections\Criteria. I can use findBy with order and then use matching method to filter records, but I would rather do that on the database side.

EDIT 2:

I use Nette with Kdyby/Doctrine. Didn't know that user.active is implemented in Kdyby/doctrine and not in Doctrine directly. So I suppose this question won't be answered..


Solution

  • If you look at Kdyby/Doctrine, is extends the findBy capabilities by automatically detecting relations and performing join if needed as cane seen here by calling autoJoinOrderBy. This is the reason why criteria does not support join, and Kdyby's findBy does.

    If you want reusable way to build Doctrine queries, the Criteria does not help you with that, but there is QueryObject, which does the similar job and lets you reuse logical query parts, but using QueryBuilder. It is not so well documented, but here are some resources:

    Official documentation of QueryObject

    Blog post with example usage

    Kdyby/Doctrine autor's presentation on Doctrine and QueryObject (from slide 43)

    Some more official information about QueryObjects