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