我目前在Zend Framework 2中遇到分页问题。
此代码
public function findAllByCriteria(CourseSearchInput $input) {
$concatDelimiter = self::CONCAT_DELIMITER;
$select = new Select();
$where = new Where();
$having = new Having();
$select->columns(array(
'id', 'title', 'description'
));
$select->from($this->tableGateway->getTable());
$select
->join('coursedata', 'courses.id = coursedata.id', array(
'relevance' => $this->buildRelevanceExpressionFromCriteria($input)
))
;
$having
->greaterThanOrEqualTo('relevance', self::RELEVANCE_MIN);
;
$select->where($where, Predicate::OP_AND);
$select->having($having);
$select->group(array('courses.id'));
$dbAdapter = $this->tableGateway->getAdapter();
// $dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');
$adapter = new \Zend\Paginator\Adapter\DbSelect($select, $dbAdapter);
$paginator = new \Zend\Paginator\Paginator($adapter);
return $paginator;
}
创建此SQL:
SELECT
`courses`.`id` AS `id`,
`courses`.`title` AS `title`,
`courses`.`description` AS `description`,
MATCH (coursedata.title) AGAINST ('Salsa') * 5 + MATCH (coursedata.description) AGAINST ('Salsa') * 2 AS `relevance`
FROM `courses`
INNER JOIN `coursedata` ON `courses`.`id` = `coursedata`.`id`
GROUP BY `courses`.`id`
HAVING `relevance` >= '3'
如果sql_mode
设置为ONLY_FULL_GROUP_BY
,则会MySQL Extensions to GROUP BY
使用并且无法执行。因此,我尝试在执行语句之前重置sql_mode
(请参阅上面注释掉的行:$dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');
)。但它没有奏效。那么,如何设置sql_mode
以执行我的非标准SQL?
答案 0 :(得分:1)
这可能不是您要问的问题的答案,但无论何时使用Paginator,我都会发现您的查询会出现问题。
Paginator的DbSelect适配器不喜欢那里的聚合函数(Group By)
Paginator将尝试使用您的查询构建自己的查询来计算集合中项目的“计数”。由于您在查询中使用聚合,因此会破坏,任何组等都会破坏适配器。
如果您检查默认实现,您将看到:
/**
* Returns the total number of rows in the result set.
*
* @return integer
*/
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
$select = clone $this->select;
$select->reset(Select::COLUMNS);
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
// This won't work if you've got a Group By in your query
$select->columns(array('c' => new Expression('COUNT(1)')));
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$row = $result->current();
$this->rowCount = $row['c'];
return $this->rowCount;
}
这与您使用Group BY时不一样,并且会返回错误的结果。
您可以创建自己的adataper,并在计划使用Group BY时扩展现有的DbSelect并覆盖count方法;
在我的脑海中,这样的东西应该可行,但可能不是最有效的方式
/**
* Returns the total number of rows in the result set.
*
* @return integer
*/
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
/**
* If the query hasn't got 'GROUP BY' just try and use the old method
*/
$stateGroup = $this->select->getRawState('group');
if( ! isset($stateGroup) || empty($stateGroup)) {
return parent::count();
}
$select = clone $this->select;
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$this->rowCount = $result->count();
return $this->rowCount;
}