您的位置:首页 > 数据库 > Oracle

ThinkPHP3.1.2的DbOracle.class.php不能实现分页的解决方法

2013-06-26 10:39 656 查看
ThinkPHP3.1.2的DbOracle.class.php不能分页的解决办法

我们发现, 在解析Limit的方法中, 存在一处错误, TP/Extend/Driver/Db/DbOracle.class.php

public function parseLimit($limit) {
$limitStr    = '';
if(!empty($limit)) {
$limit	=	explode(',',$limit);
if(count($limit)>1)
$limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0]+$limit[1]) . ")";
else
$limitStr = "(numrow>0 AND numrow<=".$limit[0].")"; // 这种方法实现分页, 是错的!
}
return $limitStr?' WHERE '.$limitStr:'';
}


parseLimit()方法生成limit条件是错的! 我们先不修改这里的代码!

接着看, TP/Lib/Core/Db.class.php 中的 buildSelectSql() 方法, 其中这句是生成sql字符串的:

$sql = $this->parseSql ( $this->selectSql, $options );


这涉及到了另一个方法 parseSql() !

我们在 Db.class.php 中找到它, 这个方法实际就是用 $options 分别替换 select 语句中的变量,

如果我们把 limit 相关的替换给注释掉, 然后组装成我们正确的sql语句, 那就OK了!

最终代码如下, 其中标注 edited 和 added 是修改或新增的代码:

public function parseSql($sql, $options = array()) {
$sql = str_replace ( array (
'%TABLE%',
'%DISTINCT%',
'%FIELD%',
'%JOIN%',
'%WHERE%',
'%GROUP%',
'%HAVING%',
'%ORDER%',
// '%LIMIT%', // edited
'%UNION%',
'%COMMENT%'
), array (
$this->parseTable ( $options ['table'] ),
$this->parseDistinct ( isset ( $options ['distinct'] ) ? $options ['distinct'] : false ),
$this->parseField ( ! empty ( $options ['field'] ) ? $options ['field'] : '*' ),
$this->parseJoin ( ! empty ( $options ['join'] ) ? $options ['join'] : '' ),
$this->parseWhere ( ! empty ( $options ['where'] ) ? $options ['where'] : '' ),
$this->parseGroup ( ! empty ( $options ['group'] ) ? $options ['group'] : '' ),
$this->parseHaving ( ! empty ( $options ['having'] ) ? $options ['having'] : '' ),
$this->parseOrder ( ! empty ( $options ['order'] ) ? $options ['order'] : '' ),
// $this->parseLimit ( ! empty ( $options ['limit'] ) ? $options['limit'] : '' ), // edited
$this->parseUnion ( ! empty ( $options ['union'] ) ? $options ['union'] : '' ),
$this->parseComment ( ! empty ( $options ['comment'] ) ? $options ['comment'] : '' )
), $sql );
// added [
list ( $r1, $r2 ) = explode ( ',', $options ['limit'] );
$r2 = $r1 + $r2;
if( '' !== $r1 ){ // page() 方法存在时
if (1 == $r1) { // limit 1
$sql = "
SELECT *
FROM (SELECT E.*, ROWNUM rn
FROM ({$sql}) E
WHERE ROWNUM <= 1)
WHERE rn >= 1
";
} else { // x < rounum < y
$sql = "
SELECT *
FROM (SELECT E.*, ROWNUM rn
FROM ({$sql}) E
WHERE ROWNUM <= {$r2})
WHERE rn > {$r1}
";
}
}
// added ]
return $sql;
}


--------------------------------------------------------------

最后, 修补一个小bug, TP/Lib/Core/Db.class.php 中的 buildSelectSql() 方法, 其中代码块

if ( strpos ( $options['page'],',' ) ) {
list ( $page, $listRows ) = explode ( ',', $options ['page'] );
} else {
$page = $options ['page'];
}


中的 strpos 函数返回可能为 0 , 所以不能那样判断, 必须改成

if( false !== strpos($options['page'], ',') )


就OK了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐