【问题标题】:How to use pagination with JOINs in Zend Framework 2?如何在 Zend Framework 2 中使用 JOIN 分页?
【发布时间】:2016-09-12 10:02:47
【问题描述】:

在一个应用程序中,我实现了一个Mapper 来从数据库中检索数据并从ResultSet 中检索对象。为了获得所有数据,我必须JOIN 多个表。然后我得到一个结构如下的巨大数组:

[
    0 => [
        main_id => 1,
        main_title => 'lorem',
        main_desc => 'ipsum',
        foo_id => '12',
        foo_name => 'qwer',
        bar_id => '56',
        bar_name => 'asdf'
    ],
    1 => [
        main_id => 1,
        main_title => 'lorem',
        main_desc => 'ipsum',
        foo_id => '12',
        foo_name => 'qwer',
        bar_id => '67',
        bar_name => 'hjkl'
    ],
    2 => [
        main_id => 1,
        main_title => 'lorem',
        main_desc => 'ipsum',
        foo_id => '23',
        foo_name => 'uiop',
        bar_id => '67',
        bar_name => 'hjkl'
    ],
    ...
    10 => [
        main_id => 1,
        main_title => 'lorem',
        main_desc => 'ipsum',
        foo_id => '23',
        foo_name => 'uiop',
        bar_id => '91',
        bar_name => 'cvbn'
    ],
    11 => [
        main_id => 2,
        main_title => 'dolor',
        main_desc => 'sit',
        foo_id => '78',
        foo_name => 'fghj',
        bar_id => '89',
        bar_name => 'vbnm'
    ],
    ...
    12 => [
        main_id => 3,
        foo_id => '135',
        bar_id => '246',
        ...
    ],
    13 => [
        main_id => 3,
        foo_id => '135',
        bar_id => '468',
        ...
    ],
    14 => [
        main_id => 3,
        foo_id => '357',
        bar_id => '680',
        ...
    ],
    ...
    1000 => [
        ...
    ]
]

然后我遍历数组,构建对象(MainFooBar 等)并将它们组合起来,例如

$newMain = $myMainHydrator->hydrate($results[0]);
$newFoo = $myFooHydrator->hydrate($results[0]);
$newBar = $myBarHydrator->hydrate($results[0]);
$newFoo->setBar($newBar);
$newMain->setFoo($newFoo);
$resultObjects[] = $newMain;

现在我建立了一个Paginator 并遇到了以下问题:Paginator 设置了一个LIMIT,例如10,然后只检索 10 行,而我需要为每个对象提供多个结果行(目前甚至是 12 行)。

我不敢相信Paginator 无法处理JOINs,所以必须有办法让它工作。如何将Paginator 用于复杂的SELECTs 和JOINs?

【问题讨论】:

    标签: php pagination zend-framework2 zend-db zend-db-select


    【解决方案1】:

    可以通过在Paginator AdaptergetItems(...) 中将LIMIT 子句替换为IN 来解决此问题。

    namespace Foo\Paginator\Adapter;
    
    use Zend\Db\Sql\Select;
    use Zend\Paginator\Adapter\DbSelect;
    use Zend\Db\Sql\Sql;
    use Zend\Db\Sql\Expression;
    
    class FooPaginatorAdapter extends DbSelect
    {
    
        public function count()
        {
            $select = new Select();
            $select->from('foo')->columns([self::ROW_COUNT_COLUMN_NAME => new Expression('COUNT(*)')]);
    
            $statement = $this->sql->prepareStatementForSqlObject($select);
            $result    = $statement->execute();
            $row       = $result->current();
            $this->rowCount = $row[self::ROW_COUNT_COLUMN_NAME];
    
            return $this->rowCount;
        }
    
        public function getItems($offset, $itemCountPerPage)
        {
            $select = clone $this->select;
            // replaced
            // $select->offset($offset);
            // $select->limit($itemCountPerPage);
            // by this
            $relevantIds = $this->getRelevantIds($offset, $itemCountPerPage);
            $select->where->in('foo.id', $relevantIds);
    
            $statement = $this->sql->prepareStatementForSqlObject($select);
            $result    = $statement->execute();
    
            $resultSet = clone $this->resultSetPrototype;
            $resultSet->initialize($result);
    
            return iterator_to_array($resultSet);
        }
    
        protected function getRelevantIds($offset, $itemCountPerPage)
        {
            $sql = new Sql($this->sql->getAdapter());
            $select = $sql->select('foo');
            $select->columns(['id']);
            $select->offset($offset);
            $select->limit($itemCountPerPage);
    
            $statement = $this->sql->prepareStatementForSqlObject($select);
            $result    = $statement->execute();
    
            $resultArray = iterator_to_array($result);
    
            $relevantIds = array_column($resultArray, 'id');
    
            return $relevantIds;
        }
    
    }
    

    正如您在本例中看到的,IDs 首先必须通过单独的数据库请求进行检索。但无论如何——它有效。如果您知道更好的解决方案,请随时发布。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      相关资源
      最近更新 更多