我有一个 itemid 和一个 category id 都是有条件的。如果没有给出,则所有项目都显示为最新的拳头。如果给定了 itemid,则仅显示 id 低于给定 id 的项目(用于分页)。如果给定类别 id,则仅显示某个类别中的项目,如果同时给出两个类别,则仅显示某个类别中的项目 id 小于 itemid 的项目(按类别显示的项目下一页)。
因为参数是有条件的,所以在构建 SQL 字符串时,你会根据参数得到很多 if 语句(伪代码我用 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");
}
可悲的是,事实并非如此,最后一个将覆盖第一个
我想出的是这个(在 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);
所以问题是:有没有更好的方法?
我想如果学说有一个转义字符串的功能,我可以摆脱第二轮 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));
}
感谢您阅读本文,希望您能启发我。
[更新]
我目前正在使用虚拟 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);
}