Предполагая, что ваше вложение имеет только один уровень глубины, вы можете использовать этот код, чтобы найти всех родителей, затем выполнить итерацию по ним и отобразить всех их дочерних элементов в качестве подсписка.
$parents = array_filter($arr, function ($item) { return !$item['parent'];});
echo "<ul>\n";
foreach ($parents as $parent) {
echo "<li>{$parent['name']}</li>\n";
// find the children
$children = array_filter($arr, function ($item) use ($parent) { return $item['parent'] == $parent['id']; });
if (!empty($children)) {
echo "<ul>\n";
foreach ($children as $child) {
echo "<li>{$child['name']}</li>\n";
}
echo "</ul>\n";
}
}
echo "</ul>\n";
Вывод (для ваши данные образца):
<ul>
<li>cat1</li>
<ul>
<li>subcat1</li>
</ul>
<li>cat2</li>
<ul>
<li>subcat2</li>
</ul>
</ul>
или как HTML:
cat2
Демонстрация на 3v4l.org
Если вы можете иметь вложение глубже, чем на один уровень, вы нужно переписать приведенный выше код как рекурсивную функцию:
function list_item($arr, $item) {
echo "<li>{$item['name']}</li>\n";
// find any children
$children = array_filter($arr, function ($i) use ($item) { return $i['parent'] == $item['id']; });
if (!empty($children)) {
echo "<ul>\n";
foreach ($children as $child) {
list_item($arr, $child);
}
echo "</ul>\n";
}
}
$parents = array_filter($arr, function ($item) { return !$item['parent'];});
echo "<ul>\n";
foreach ($parents as $parent) {
list_item($arr, $parent);
}
echo "</ul>\n";
Демонстрация на 3v4l.org