CakePHP 3.8 конвертирует массив в Cake\ORM\Entity
В настоящее время я участвую в проекте CakePHP и не знаю, как передать измененный запрос / массив в средство разбиения на страницы.
Вот мой контроллер:
public function index($fooElement = '')
{
$query = $this->Properties->find()->where(['fooElement' => $fooElement]);
//The fooFunction needs an array cause for an internal call of cakes HASH::NEST function
$data= $this->FooModel->_fooFunction($query->enableHydration(false)->toList();
//Error: Not a paginable object
$data = $this->paginate($data)
$this->set(compact('fooElement', 'data'));
$this->set('_serialize', ['data']);
if (empty($fooElement)) {
$this->render('otherView');
}
}
РЕДАКТИРОВАТЬ: Вот функция fooFunction:
public function _fooFunction($data)
{
$out = [];
$cache = [];
$nested = Hash::nest($data, ['idPath' => '{n}.id', 'parentPath' => '{n}.parent_id']);
$out = $this->_setOrderAndLevel($nested);
return $out;
}
protected function _setOrderAndLevel($items, $level = 0, $number = 0)
{
$out = [];
$items = Hash::sort($items, '{n}.orderidx');
foreach ($items as $item) {
$item['level'] = $level;
if (!empty($item['children'])) {
$children = $item['children'];
unset($item['children']);
$out[] = $item;
$out = array_merge($out, $this->_setOrderAndLevel($children, $level + 1));
} else {
$out[] = $item;
}
}
return ($out);
}
В _fooFunction
принимает приведенный запрос к базе данных, вносит некоторые изменения, добавляет два новых свойства и возвращает вложенный массив. Это картыid
с parent_id
для получения детей и описания уровня. Описание уровня будет использоваться для отступов в представлении для отображения иерархического порядка.
ВАЖНОЕ ЗАМЕЧАНИЕ: я уже опасаюсь TreeBehavior в CakePHP, но проблема в том, что в нашей базе данных нет левых / правых полей, и я не могу их добавить. В рамках этого проекта я должен выбрать этот путь. Однако$data
содержит именно то, что я хочу, но мне нужно преобразовать его в совместимый объект для разбивки на страницы.
РЕДАКТИРОВАТЬ: Благодаря ndm я смог построить объект с возможностью разбивки на страницы с необходимыми ограничениями. Последняя проблема, которая все еще стоит передо мной, - это объединить всех дочерних элементов и возможных дочерних элементов. У родителя может быть n детей, а также у детей иногда может быть n дочерних детей. Поэтому я решил это с помощью рекурсивного вызова моей функции _setOrderAndLevel внутри fooFunction.
Это текущая структура:
array(
[0] = fooEntity(
id = 1,
orderidx = 1,
parentId = null,
level = 0,
children(
id = 2,
orderidx = 2,
parentId = 1,
level = 1
children(
id = 3,
orderidx = 3,
parentId = 2,
level = 2
........
Но должно быть так:
array(
[0] = fooEntity(
id = 1,
orderidx = 1,
parentId = null
level = 0
[1] = fooEntity(
id = 2,
orderidx = 2,
parentId = 1,
level = 1
[2] = fooEntity(
id = 3,
orderidx = 3,
parentId = 2,
level = 2
........
Я попытался создать второе средство форматирования результатов, но оно не работает:
...
return $results
->nest('id', 'parent_id', 'children')
->map($decorate);
})
->formatResults(function (\Cake\Collection\CollectionInterface $results) {
return $results->map(function ($data) {
call_user_func_array('array_merge', $data);
});
});
Maybe a "combine->" call could be the solution but I am not sure. Any help is welcome
1 ответ
Как правило, если вам нужно каким-то образом отформатировать результаты, вам, скорее всего, следует использовать средство форматирования результатов, чтобы иметь возможность сохранить объект запроса нетронутым, и ром, глядя на результирующий формат, который создает ваша функция, это то, что вы должны использовать в данном случае - средство форматирования результатов.
Если вам нужен порядок, вы можете сделать это уже на уровне SQL, а для вложения результатов вы можете использовать коллекцию результатов nest()
метод, то есть вы можете отказаться от использования Hash
учебный класс:
$query = $this->Properties
->find()
->where(['fooElement' => $fooElement])
->order(['orderidx' => 'ASC'])
->formatResults(function (\Cake\Collection\CollectionInterface $results) {
$fold = function ($rows, $level = 0) use (&$fold) {
$folded = [];
foreach ($rows as $row) {
$row['level'] = $level;
$children = $row['children'] ?: null;
unset($row['children']);
$folded[] = $row;
if ($children) {
$folded = array_merge(
$folded,
$fold($children, $level ++)
);
}
}
return $folded;
};
$nested = $results->nest('id', 'parent_id', 'children');
$folded = $fold($nested);
return collection($folded);
});
Обратите внимание, что вы должны вернуть экземпляр \Cake\Collection\CollectionInterface
из средства форматирования результатов. В документах говорится, что возврата итератора (y) было бы достаточно, но как только будут добавлены дополнительные средства форматирования, ожидающие коллекцию, все сломается.
Смотрите также