Урок 23. Как использовать рекурcивную функцию в php?

Рекурcия (или рекурcивный вызов) – это когда функция вызывает саму себя. Рекурсия довольно часто используется в php-скриптах. Но необходимо учитывать то, что данная операция использует много ресурсов.

Давайте рассмотрим рекурсию не реальном примере.  Допустим у нас есть сайт, в котором существует раздел «Услуги компании».   В этом разделе в свою очередь есть подраздел «Веб-разработка» с еще одним подразделом «Сайты-визитки». В результате получается иерархическая структура, с родительскими и дочерними разделами. Обратите внимание, раздел «Веб-разработка»  является родительским для подраздела «Сайты-визитки» и дочерним для раздела «Услуги компании». Нужно составить cкрипт, который позволит  проверять наличие подразделов у любого раздела.

Для начала изобразим структуру сайта в форме массива:

<?php
$menu = array(
1 => array(
"name" => "Услуги компании",
"parent" => 0   
),
2 => array(
"name" => "Веб-разработка",
"parent" => 1   
),
3 => array(
"name" => "Сайты-визитки",
"parent" => 2   
)
);
?>

Массив $menu состоит из 3 элементов. (Мы специально начали нумерацию c 1, чтобы 0 был свободен). Индексы элементов (1, 2 и 3) являются уникальными идентификаторами. Каждому элементу присвоено 2 поля:
name – название раздела;
parent – номер родительского раздела.

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

<?php
function has_child($arr,$page_id=0){
foreach($arr as $index => $field); {
if ($field["parent"] == $page_id) {
if ($page_id != 0){
echo $arr[$page_id]["name"]  . "имеет  подраздел<br>";
}
//Здесь будет рекурсия!!!
has_child($arr, $index);
}
}
}
//Вызываем функцию 1 раз
//Остальные будут выполнены рекурсивно
has_child(&menu);
?>

Напоминание! При запуске этого примера на выполнение, не забудьте дописать в него массив $menu.

Теперь давайте пошагово рассмотрим выполнение данной функции.  При первом вызове в качестве входных данных в функцию поступает ссылка на масив $menu и корневой элемент, тот самый, свободный, с нулевым индексом, для которого с помощью конструкции foreach ищем подразделы. С помощью рекурсии каждый найденный потомок проверяется на наличие подразделов. При этом нам не нужно вручную для каждого элемента вызывать функцию. Она самостоятельно обходит все элементы массива. Подобного рода перебор иерархической цепочки называется рекурсивным спуском.

При использовании рекурсии в php скриптах важно отслеживать условия ее окончания. В ином случае скрипт может «зациклится», что негативно повлияет на работу сервера.