1

我目前在 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'

如果设置为,则它使用MySQL Extensions to GROUP BY并且无法执行。所以,我试图在语句执行之前重置(见上面注释掉的行:)。但它没有奏效。那么,我该如何设置才能执行我的非标准 SQL 呢?sql_modeONLY_FULL_GROUP_BYsql_mode$dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');sql_mode

4

1 回答 1

1

这可能不是您所问问题的答案,但我可以看到无论何时使用 Paginator,您的查询都会遇到问题。

分页器的 DbSelect 适配器不喜欢其中的聚合函数(分组依据)

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;
}
于 2013-04-16T08:39:26.523 回答