Иерархический массив PHP - Родители и дети


Я использую PHP и MySQL с Идиомой. Это может быть неуместно.

Мой PHP массив

  • Это отношения между родителями и детьми.
  • 0 является корневым родителем.
  • Пример: У корневого родителя 0 есть дочерний элемент 33, у которого есть дочерний элемент 27, у которого есть дочерний элемент 71.

Эта структура массива может быть изменена, если это необходимо для решения проблемы.

array (
  33 => 
    array (
      0 => '27',
      1 => '41',
  ),
  27 => 
    array (
      0 => '64',
      1 => '71',
  ),
  0 => 
    array (
      0 => '28',
      1 => '29',
      2 => '33',
  ),
)

Мой иерархический результат

Что-то вот так, но в виде массива...

  0 => 
      28
      29
      33
         27 =>
               64
               71
         41

Информация

  • Глубина неизвестна, и она может быть неограниченной. Я пробовал foreach, но, возможно, это не тот путь.

Мои собственные мысли

  • Какая-то рекурсивная функция?
  • Некоторые циклы while?

Я попробовал оба вышеперечисленных способа, но просто запутался. Это очень сложно.

Author: Jens Törnell, 2012-12-14

3 answers

Предложение @deceze сработало. Однако входной массив должен немного измениться, вот так...

$rows = array(
    array(
        'id' => 33,
        'parent_id' => 0,
    ),
    array(
        'id' => 34,
        'parent_id' => 0,
    ),
    array(
        'id' => 27,
        'parent_id' => 33,
    ),
    array(
        'id' => 17,
        'parent_id' => 27,
    ),
);

Из https://stackoverflow.com/a/8587437/476:

function buildTree(array $elements, $parentId = 0) {
    $branch = array();

    foreach ($elements as $element) {
        if ($element['parent_id'] == $parentId) {
            $children = buildTree($elements, $element['id']);
            if ($children) {
                $element['children'] = $children;
            }
            $branch[] = $element;
        }
    }

    return $branch;
}

$tree = buildTree($rows);

print_r( $tree );
 39
Author: Jens Törnell, 2017-05-23 11:54:46

Я добавил в ответы @Jens Törnell, чтобы включить определение параметров для имени столбца parent_id, имени ключа массива дочерних элементов, а также имени столбца для идентификатора.

/**
 * function buildTree
 * @param array $elements
 * @param array $options['parent_id_column_name', 'children_key_name', 'id_column_name'] 
 * @param int $parentId
 * @return array
 */
function buildTree(array $elements, $options = [
    'parent_id_column_name' => 'parent_id',
    'children_key_name' => 'children',
    'id_column_name' => 'id'], $parentId = 0)
    {
    $branch = array();
    foreach ($elements as $element) {
        if ($element[$options['parent_id_column_name']] == $parentId) {
            $children = buildTree($elements, $options, $element[$options['id_column_name']]);
            if ($children) {
                $element[$options['children_key_name']] = $children;
            }
            $branch[] = $element;
        }
    }
    return $branch;
}

Поскольку функциональность довольно универсальна, мне удалось использовать вышеуказанную функцию в большинстве моих проектов.

 5
Author: Fariz Luqman, 2017-01-09 09:55:46

Отличный ответ от @Jens Törnell, просто хотел добавить небольшое улучшение: если ваш parent_id и идентификатор на самом деле являются строкой, а не числом, то описанный выше метод завершится неудачей, и после создания дочернего массива он снова создаст эти дочерние массивы как отдельный отдельный массив. Чтобы исправить это, вы должны выполнить тройную равную проверку и указать тип данных переменной, т. Е. (строка) для сравнения.

Для идентификатора на основе строки и идентификатора родителя в массив

function buildTree(array $elements, $parentId = 0) {
    $branch = array();

    foreach ($elements as $element) {
        if ((string)$element['parent_id']  === (string)$parentId) {
            $children = buildTree($elements, $element['id']);
            if ($children) {
                $element['children'] = $children;
            }
            $branch[] = $element;
        }
    }

    return $branch;
}

Кроме того, если кто-то пожелает, он также может добавить третий параметр в функцию, чтобы динамически указывать тип данных переменных, т. Е. function buildTree(array $elements, $parentId = 0, $datatype='string'), но тогда вам придется учитывать любые другие ошибки.

Надеюсь, это кому-нибудь поможет!

 3
Author: Danish, 2018-02-03 06:45:32