“任氏有无轩”的后台中有一个统计是得出每天对书籍详情页面的访问数量,结果集很简单:一个日期,一个该天的访问次数。
在原生SQL下,这个并不复杂,如下的语句就可以完成: select count(v.bid) vc, date(from_unixtime(v.visitwhen+15*60*60)) vd from book_visit v group by vd order by vd。
但是这个语句稍作变动(将book_visit改为FQN的引用)在SF2中用常规的createQuery将不能执行,提示date函数不被支持。
解决这个问题有两种方法,一种是quick-and-dirty的纯原生SQL:
$q = $em->getConnection()->prepare('select count(v.bid) vc, date(from_unixtime(v.visitwhen+8*60*60)) vd from book_visit v group by vd order by vd');
$q->execute();
return $q->fetchAll();
这个方法简单明了,适合初学者使用。
作为SF2和Doctrine的推荐方法,我们要使用所谓的ResultSetMapping和createNativeQuery。
我们可以这样简单的理解,ResultSetpMapping提供了一种映射机制,将原生SQL返回的字段映射到结果集的域,从而使得Doctrine可以以此构造返回的结果集,然后执行SQL语句,并将结果返回。
应该说,即使你不使用createNativeQuery,而只是用createQuery,Doctrine也还是会隐含的做一个ResultSetMapping的,只是不用显式调用罢了。
代码如下:
public function getVisitCountByDay()
{
$em = $this->getEntityManager();
$rsm=new DoctrineORMQueryResultSetMapping;
$rsm->addScalarResult('vc', 'vc');
$rsm->addScalarResult('vd', 'vd');
$q=$em->createNativeQuery('select count(v.bid) vc, date(from_unixtime(v.visitwhen+15*60*60)) vd from book_visit v group by vd order by vd', $rsm);
$res=$q->getResult();
return $res;
}
这个调用中,最关键的其实是两个addScalarResult。 vc是标量结果很自然,但是vd为什么是标量结果?Doctrine的文档对此语焉不详。
我的理解是,一旦结果集中包含了一个标量结果(vc),那么所有其它结果也自然要变为标量结果。STOP。
本文收录于[go4pro.org]