在一个应用程序中,我实现了一个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 => [
...
]
]
然后我遍历数组,构建对象(Main
,Foo
,Bar
等),然后将它们组合起来,例如
$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
无法处理JOIN
,因此必须有办法让它发挥作用。如何使用Paginator
复杂SELECT
与JOIN
s?
答案 0 :(得分:1)
可以通过LIMIT
IN
Paginator
中的Adapter
替换getItems(...)
条款来解决此问题。
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;
}
}
正如您在本案中所看到的,首先必须使用单独的数据库请求检索ID
。但无论如何 - 它有效。如果您知道更好的解决方案,请随时发布。