我的itemid和类别ID都是有条件的。如果没有给出,则所有项目都显示为最新的拳头。如果给出itemid,则仅显示id低于给定id的项目(用于分页)。如果给出类别ID,则仅显示特定类别中的项目,并且如果两者都被给出,则仅给出项目ID小于itemid的特定类别中的项目(按类别下一页的项目)。
因为参数是有条件的,所以在构建SQL字符串时会得到很多if语句,这取决于params(伪代码我用PHP填充了我的美元符号):
if itemid ' where i.iid < :itemid '
if catid
if itemid
' and c.id = :catid'
else
' where c.id = :catid'
end if
end if
如果给出更多可选参数,这将变得非常混乱,所以我想我会尝试使用createQueryBuilder。希望有这样的事情:
if($itemId!==false){
$qb->where("i.id < :id");
}
if($categoryId!==false){
$qb->where("c.id = :catID");
}
遗憾的是,情况并非如此,最后的地方overwrite the first one
我想出的是(在Symfony2中):
private function getItems($itemId,$categoryId){
$qb=$this->getDoctrine()->getRepository('mrBundle:Item')
->createQueryBuilder('i');
$arr=array();
$qb->innerJoin('i.categories', 'c', null, null);
$itemIdWhere=null;
$categoryIdWhere=null;
if($itemId!==false){
$itemIdWhere=("i.id < :id");
}
if($categoryId!==false){
$categoryIdWhere=("c.id = :catID");
}
if($itemId!==false||$categoryId!==false){
$qb->where($itemIdWhere,$categoryIdWhere);
}
if($itemId!==false){
$qb->setParameter(':id', $itemId);
}
if($categoryId!==false){
$arr[]=("c.id = :catID");
$qb->setParameter(':catID', $categoryId);
}
$qb->add("orderBy", "i.id DESC")
->setFirstResult( 0 )
->setMaxResults( 31 );
我并不完全信任$qb->where(null,null)
,尽管它目前没有创建错误或意外结果。看起来这些参数被忽略了。无法在文档中找到任何内容,但空字符串会生成错误$qb->where('','')
。
我仍然看起来有点笨拙,如果我可以使用多个$qb->where(condition)
那么每个可选项只需要一个if语句$qb->where(condition)->setParameter(':name', $val);
所以问题是:有更好的方法吗?
我想如果doctrine有一个函数来逃避字符串我可以摆脱第二个if语句轮次(不确定恶意用户是否可以在允许sql注入的不同字符集中发布一些东西):
private function getItems($itemId,$categoryId){
$qb=$this->getDoctrine()->getRepository('mrBundle:Item')
->createQueryBuilder('i');
$arr=array();
$qb->innerJoin('i.categories', 'c', null, null);
$itemIdWhere=null;
$categoryIdWhere=null;
if($itemId!==false){
$itemIdWhere=("i.id < ".
someDoctrineEscapeFunction($id));
}
感谢您阅读本文,希望您能够启发我。
[UPDATE]
我目前正在使用虚拟where语句,因此可以使用andWhere添加任何其他条件语句:
$qb->where('1=1');// adding a dummy where
if($itemId!==false){
$qb->andWhere("i.id < :id")
->setParameter(':id',$itemId);
}
if($categoryId!==false){
$qb->andWhere("c.id = :catID")
->setParameter(':catID',$categoryId);
}
答案 0 :(得分:1)
如果要使用更通用的方法来处理此问题,可以创建过滤器。 Doctrine 2.2提供了一个过滤系统,允许开发人员将SQL添加到查询的条件子句中
了解有关filters的更多信息,但我正以与您展示的方式类似的方式处理此问题