des1roer
@des1roer
ученье - свет, а неученье - приятный полумрак

PHP Рекурсивный обход данных из базы?

Вроде тема изъезженная, но вот наткнуться на реализацию не могу. есть таблица типовая ид\имя\ид предка. хочу добится такого
array
(
    1 => array
    (
        'text' => 'page/index'
        'id' => 4
        'expanded' => false
        'children' => array
        (
            0 => array
            (
                'text' => 'site/index'
                'id' => 5
                'expanded' => false
            )
        )
    )
    4 => array
    (
        'text' => '222'
        'id' => 2
        'expanded' => false
        'children' => array
        (
            0 => array
            (
                'text' => '3'
                'id' => 3
                'expanded' => false
                'children' => array
                (
                    0 => array
                    (
                        'text' => '4'
                        'id' => 7
                        'expanded' => false
                    )
                )
            )
            1 => array
            (
                'text' => '22222'
                'id' => 8
                'expanded' => false
            )
        )
    )

нужно рекурсивно пробежаться по всем полученным данным и в зависимости какой ид предка закинуть в тот массив. у корня ид предка соотвественно нулл
что имею
array(9) {
  [0]=>
  array(3) {
    ["id"]=>
    int(3)
    ["text"]=>
    string(1) "3"
    ["parent_id"]=>
    int(2)
  }
  [1]=>
  array(3) {
    ["id"]=>
    int(4)
    ["text"]=>
    string(10) "page/index"
    ["parent_id"]=>
    int(1)
  }
  [2]=>
  array(3) {
    ["id"]=>
    int(5)
    ["text"]=>
    string(10) "site/index"
    ["parent_id"]=>
    int(4)
  }
  [3]=>
  array(3) {
    ["id"]=>
    int(7)
    ["text"]=>
    string(1) "4"
    ["parent_id"]=>
    int(3)
  }
  • Вопрос задан
  • 3096 просмотров
Решения вопроса 1
des1roer
@des1roer Автор вопроса
ученье - свет, а неученье - приятный полумрак
$a = Page::model()->findAll();
foreach ($a as $user)
{
        $all[$user->p_parent][] = array(id => $user->p_id, text=> $user->p_title, parent_id => $user->p_parent);   
}
function RecursiveTree2(&$rs, $parent)
{
    $out = array();
    if (!isset($rs[$parent]))
    {
        return $out;
    }
    foreach ($rs[$parent] as $row)
    {
        $chidls = RecursiveTree2($rs, $row['id']);
        if ($chidls)
        {
            $row['expanded'] = false;
            $row['children'] = $chidls;            
        }
        $out[] = $row;
    }
    return $out;
}
$this->widget('CTreeView', array('data' => RecursiveTree2($all ,0), 'htmlOptions' => array('class' => 'treeview-red')));

дамп массива
array(7) {
  [2]=>
  array(2) {
    [0]=>
    array(3) {
      ["id"]=>
      int(3)
      ["text"]=>
      string(1) "3"
      ["parent_id"]=>
      int(2)
    }
    [1]=>
    array(3) {
      ["id"]=>
      int(8)
      ["text"]=>
      string(5) "22222"
      ["parent_id"]=>
      int(2)
    }
  }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
akubintsev
@akubintsev
Опытный backend разработчик
Именно в таком виде из реляционной БД вы не сможете получить данные. Тут либо nosql решения, либо самостоятельно приводить к такому виду через рекурсивный запрос. Только у MySQL с этим проблема, придется писать хранимую процедуру.
Ответ написан
IvanCher
@IvanCher
Мысли шире
$sourceArray = *предполагаю, что извлекли все записи из базы*;
$newArray = [];
foreach ($sourceArray as $el) {
    if ($el['parent_id']) {
        $newArray[$el['parent_id']]['children'] = [
            'id' => $el['id'],
            'text'=>$el['text'],
            ...
        ];
    } else {
        $newArray[$el['id']] = [
            'id' => $el['id'],
            'text'=>$el['text'],
            ...
        ];
    }
}

подойдет ?
Ответ написан
@Ramallah
Сколько уже копий сломано на деревьях основанных только на parent_id. Ведь если дерево разрастется, то выборка может занимать много SQL запросов.

Опять же в зависимости от условий задачи может быть несколько вариантов решений. Но я склоняюсь к применению метода nested-sets. Да, издержки на обновление дерева выше, но работать с ними в разы приятнее.

А чуток модифицировав алгоритм, у тебя останется и parent_id.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы