Иерархический массив 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?
Я попробовал оба вышеперечисленных способа, но просто запутался. Это очень сложно.
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 );
Я добавил в ответы @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;
}
Поскольку функциональность довольно универсальна, мне удалось использовать вышеуказанную функцию в большинстве моих проектов.
Отличный ответ от @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')
, но тогда вам придется учитывать любые другие ошибки.
Надеюсь, это кому-нибудь поможет!