Reputation: 1489
I'm trying to retrieve comments from a table Comment which has id, game (a foreign key) and date.
Every time I ask for comments I want to get 3 comments sorted by date for a specified game and I want to know if there is more comments to show later. For that, I've written two functions, the first one returns the three comments:
public function getRecentComments($offset,$id) {
$dql = "SELECT c FROM Comment c
WHERE c.game = ?1
ORDER BY c.date DESC";
$query = $this->getEntityManager()->
createQuery($dql)->
setParameter(1, (int)$id)->
setMaxResults(3)->
setFirstResult($offset);
return $query->getResult();
And the second one returns the number of comments I could get later. The reason of this function is wehter show a button "More comments" or not. This is the second function:
public function moreComments($offset,$id) {
$dql = "SELECT COUNT(c.id) FROM Comment c
WHERE c.game = ?1
ORDER BY c.date DESC";
$query = $this->getEntityManager()
->createQuery($dql)
->setParameter(1, (int)$idPartido)
->setFirstResult($offset+3)
->setMaxResults(1)
->getSingleScalarResult();
return $query;
}
But the second function doesn't work for the next error:
Fatal error: Uncaught exception 'Doctrine\ORM\NoResultException' with message 'No result was found for query although at least one row was expected.
Which I think it is due to use setFirstResult and count().
So, I've used
public function moreComments($offset,$id) {
$dql = "SELECT c FROM Comentario c
WHERE c.partido = ?1
ORDER BY c.fecha DESC";
$query = $this->getEntityManager()
->createQuery($dql)
->setParameter(1, (int)$idPartido)
->setFirstResult($offset+3)
->setMaxResults(1)
->getSingleScalarResult();
return sizeof($query);
}
Which obviously is bad written because I shouldn't get the data for only a count. How could I write the second function correctly?
Thanks in advance.
Upvotes: 1
Views: 10512
Reputation: 1624
If you will only be using MySQL, then you can take advantage of its FOUND_ROWS()
function.
This will require using native queries, which will most likely hinder your ability to use a DB other than MySQL, but it works quite well in my experience.
I have used something like the following with great success.
use Doctrine\ORM\Query\ResultSetMapping;
public function getRecentComments($offset, $id) {
$sql = "SELECT SQL_CALC_FOUND_ROWS * FROM Comment c
WHERE c.game = ?
ORDER BY c.date DESC
LIMIT ?,3";
$rsm = new ResultSetMapping();
$rsm->addEntityResult('Comment', 'c');
$rsm->addFieldResult('c', 'id', 'id');
$rsm->addFieldResult('c', 'game_id', 'game_id');
$rsm->addFieldResult('c', 'date', 'date');
$query = $this->getEntityManager()->createNativeQuery($dql, $rsm);
$query->setParameters(array(
(int)$id,
(int)$offset
));
$results = $query->getResult();
// Run FOUND_ROWS query and add to results array
$sql = 'SELECT FOUND_ROWS() AS foundRows';
$rsm = new ResultSetMapping();
$rsm->addScalarResult('foundRows', 'foundRows');
$query = $this->getEntityManager()->createNativeQuery($sql, $rsm);
$foundRows = $query->getResult();
$results['foundRows'] = $foundRows[0]['foundRows'];
return $results;
}
After getting the results array from the above function, I extract the 'foundRows' element to a separate variable, unset it (i.e., unset($results['foundRows'])
), and then continue using the array as normal.
Hope this helps.
Upvotes: 4