Как использовать нумерацию страниц с JOIN в Zend Framework 2?

В приложении я реализовал 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 не выдерживаю JOINs, поэтому должен быть способ заставить это работать. Как использовать Paginator для сложных SELECTс JOINs?

0

Решение

Проблема может быть решена путем замены LIMIT оговорка IN в Paginator Adapter«s 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Сначала нужно получить отдельный запрос к базе данных. Но в любом случае — это работает. Если вы знаете лучшее решение, пожалуйста, не стесняйтесь опубликовать его.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]