Примеры использования рекурсивной функции в php

       PHP      php    шпаргалки    полезности      2550    
PHP: Рекурсия и её использование в примерах

Рекурсия — определение, описание, изображение какого-либо объекта или процесса внутри самого этого объекта или процесса, то есть ситуация, когда объект является частью самого себя. Другими словами, рекурсия - это вызов функции внутри самой себя.

Простой пример рекурсии в PHP.

Ниже показан примитивный пример использования рекурсии. По сути, ничего полезного данный код не делает. Более того, такой скрипт (бесконечный) переполнит стэк и аварийно завершит свою работу. Мы получим ошибку: Fatal error: Uncaught Error: Maximum function nesting level of '256' reached, aborting!.

  function recursion() 
  {    
    recursion(); 
  }

  recursion();

Более полезный пример использования рекурсии

Чтобы избавится от бесполезного и бесконечного вызова функции, необходимо прописать условие при котором эта функция вызывала бы сама себя, делая при этом что-то полезное и нужное. В классическом исполнение хорошо подходит пример функции вычисляющей факториал числа.

Факториал - произведение всех целых чисел, меньших или равных данному числу.

function factorial($n) 
{
  if ($n <= 1) return 1; 
  return $n * factorial($n - 1); // здесь происходит повторный вызов функции 
} 

echo factorial(5); // 120

Факториал числа так же можно вычислить, применив цикл, полностью заменяющий рекурсию:

function factorial($n) 
{
  $result = 1; 
  for ($i = 1; $i <= $n; $i++) { 
     $result *= $i; 
  } 
  return $result; 
} 

echo factorial(5); // 120 

Пример функции для защиты от XSS

Практически все данные (за редким исключением) из форм необходимо, во избежания XSS, пропускать через функцию htmlspecialchars(). Наша задача написать такую функцию, которая будет принимать массив (включая вложенные массивы) всех входящих данных и "прогонять" эти данные через встроенную функцию php htmlspecialchars(). И как раз здесь мы будем использовать рекурсию.

<?php
function xss($data) {
  if (is_array($data)) { // Если это массив
    $result = array(); // Создаём новый массив
    foreach ($data as $key => $value) { // Перебираем исходный массив
      $result[$key] = xss($value); // Рекурсивно вызываем функцию xss
    }
    return $result; // Возвращаемый "защищённый" массив
  }
  return htmlspecialchars($data, ENT_QUOTES); // Если это не массив, то вызываем htmlspecialchars()
}


// Предположим, что в строке запроса у нас такая строка:
// /?name=John&age=<>45
$data = xss($_REQUEST); // Вызываем функцию, передав туда в качестве аргумента весь REQUEST

// Распечатаем результат
var_dump($data);

Дерево категорий

В данном примере выведем дерево категорий, используя рекурсивный метод, написанный в ООП стиле программирования. В базе есть таблица category с несколькими записями.

INSERT INTO `category` (`id`, `name`, `parent_id`) VALUES
(1, 'Компьютеры и периферия', 0),
(2, 'Комплектующие для ПК', 0),
(3, 'Смартфоны и смарт-часы', 0),
(4, 'Телевизоры и медиа', 0),
(5, 'Игры и приставки', 0),
(6, 'Аудиотехника', 0),
(7, 'Фото-видеоаппаратура', 0),
(8, 'Офисная техника и мебель', 0),
(9, 'Компьютерные системы', 1),
(10, 'Периферия', 1),
(11, 'Программное обеспечение и аксессуары', 1),
(12, 'Системные блоки', 9),
(13, 'Моноблоки', 9),
(14, 'Неттопы и компьютеры-флешки', 9),
(15, 'Платформы', 9),
(16, 'Игровые компьютеры', 12),
(17, 'Компьютеры для офиса', 12),
(18, 'Компьютеры для бизнеса', 12),
(19, 'Сенсорные моноблоки', 13),
(20, 'Моноблоки с IPS экраном', 13),
(21, 'Моноблоки с VA экраном', 13),
(22, 'Моноблоки с TN экраном', 13),
(23, 'Основные комплектующие', 2),
(24, 'Хранение данных и охлаждение', 2);

Для работы с базой данных я буду использовать PDO.

Далее я создам класс Category:

<?php
require 'DB.php';

class Category
{
  /**
   * @return array
   * Получаем все категории
   */
  public function getData()
  {
    $db = new DB();
    return $db::getRows("SELECT * FROM `category`");
  }

  /**
   * @param $data
   * @return mixed
   * Строим дерево
   */
  public function createTree($data)
  {
    $parents = [];
    foreach ($data as $key => $item):
      $parents[$item->parent_id][$item->id] = $item;
    endforeach;
    $treeElem = $parents[0];
    $this->generateElemTree($treeElem, $parents);
    return $treeElem;
  }

  /**
   * @param $treeElem
   * @param $parents
   * Генерируем элементы дерева с учётом удобного вывода потомков
   */
  private function generateElemTree(&$treeElem, $parents)
  {
    foreach ($treeElem as $key => $item):
      if (!isset($item->children)):
        $treeElem[$key]->children = [];
      endif;

      if (array_key_exists($key, $parents)):
        $treeElem[$key]->children = $parents[$key];
        $this->generateElemTree($treeElem[$key]->children, $parents);
      endif;
    endforeach;
  }

  /**
   * @param $data
   * Рендерим вид
   */
  public function renderTemplate($data) {
        echo "<ul>";
        if(is_array($data)):
            foreach ($data as $item):
                echo '<li>';
                echo "<a href=\"/?=/{$item->id}\">";
                echo $item->name;
                echo "</a>";
                if(count($item->children) > 0):
                    $this->renderTemplate($item->children);
                endif;
                echo '</li>';
            endforeach;
        endif;
        echo "</ul>";
    }
}

Выводим дерево категорий:

require 'Category.php';

$category = new Category();
$data = $category->getData();
$tree = $category->createTree($data);
$category->renderTemplate($tree);

Основы создания дерева категорий почитать можно здесь.

Комментарии временно оключены

Поиск

Популярное