Парадокс разделения кода: создайте дерево HTML из многомерного массива и сохраните HTML вне рекурсивной функции

Этот рабочий код кажется типичным решением этой проблемы.

Он берет многомерный массив, который содержит категории и их подкатегории (без подразумеваемых ограничений на то, на сколько уровней он идет) и создает из него неупорядоченный список HTML, выводя его на страницу изнутри рекурсивной функции.

Подуровни обходятся путем рекурсивной передачи значения для каждого дочернего ключа элемента массива в array_walk () из исходной функции обратного вызова с именем _category_list () _.

Как можно изменить этот метод вывода, чтобы весь HTML-код существовал в шаблоне вне функции?

Вот краткое изложение кода:

Этот многомерный массив содержит многоуровневое дерево категорий.

Важные ключи для использования в HTML - это 'category_id', 'name' и 'children'. Другие ключи были удалены из приведенного ниже массива для простоты, но если они полезны, то это: 'parent_id' и 'level' (начиная с уровня 1).

<?php

// the array containing the tree
$categories = array (
  'category_id' => '2',
  'name' => 'Top Category Name',
  'children' => array (
    0 => array (
      'category_id' => '188',
      'name' => 'Category Name',
      'children' => array (
        0 => array (
          'category_id' => '159',
          'name' => 'Category Name',
          'children' => array (),
        ),
        1 => array (
          'category_id' => '160',
          'name' => 'Category Name',
          'children' => array (),
        ),
        2 => array (
          'category_id' => '166',
          'name' => 'Category Name',
          'children' => array (),
        ),
      ),
    ),
    1 => array (
      'category_id' => '4',
      'name' => 'Category Name',
      'children' => array (
        0 => array (
          'category_id' => '141',
          'name' => 'Category Name',
          'children' => array (),
        ),
        1 => array (
          'category_id' => '142',
          'name' => 'Category Name',
          'children' => array (),
        ),
      ),
    ),
  ),
)

?>

.

Следующая функция производит большую часть вывода HTML, но блокирует HTML внутри себя.

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

<?php

// separate the HTML from this function,
// passing $v to the view template for handling
function category_list($v, $k){
  switch ($k) {
    case 'category_id':
      echo "<li id="$v">";
      break;
    case 'name':
      echo "$v";
      break;
    case 'children':
      if(count($v) > 0){
        echo "<ul>";
        foreach($v as $k=>$v)
        array_walk($v, 'category_list');
        echo "</ul>";
      }
      echo "</li>";
      break;
  }
}

?>

.

Следующий блок кода - это текущий шаблон html / php с вызовом для обхода первого уровня массива через array_walk () и ссылкой на рекурсивную функцию выше. Затем сама функция обрабатывает рекурсию и итерацию более глубоких категорий с 1 или более дочерними элементами. Конечно, это типичный подход.

В этом коде должны быть все теги HTML, а не только внешние теги.

<ul>
<?php array_walk($tree,'category_list'); ?>
</ul>

.

Идеальное решение:

Конечная цель здесь - найти способ для дизайнеров шаблонов создать свою идеальную структуру навигации без необходимости создавать или изменять функцию рекурсии (которая недоступна) и не требовать использования цикла foreach для каждого уровня многомерного множество. Решение не должно быть привязано к каким-либо конкретным ограничениям по глубине.

Примеры настроек HTML могут варьироваться от размещения дополнительных атрибутов внутри тегов ul / li или даже обертывания новых тегов вокруг выходного текста, таких как теги span, которые обычно используются в навигации для достижения эффекта раздвижных дверей с помощью CSS. Поэтому я думаю, что подходящее решение должно как минимум поддерживать эти сценарии.

Итерация по массиву из шаблона с использованием array_walk () все равно будет приемлемой, если ее можно использовать таким образом, что функция обратного вызова передает желаемые переменные обратно в шаблон для использования с HTML дизайнера.

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

Я также хочу избегать использования методов javascript для построения дерева. И если есть способ избежать использования переключателя, я тоже открыт для предложений.


person Community    schedule 21.05.2009    source источник


Ответы (1)


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

Ваш контент будет инкапсулирован внутри класса, и вы можете написать все методы и утилиты, чтобы пользователь мог манипулировать и выводить данные. Внутри класса можно также написать служебные методы для отображения количества уровней и т. Д.

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

person Paulo    schedule 21.05.2009
comment
Функция в моем примере на самом деле является методом класса каталога, который обрабатывает вызовы php из шаблона. Но я хотел, чтобы пример был простым, поэтому я не упомянул существующую объектно-ориентированную структуру. Но по этой причине HTML нужно держать вне функции. Поэтому в этом контексте я не уверен, как бы применить вашу концепцию. Вы думали о чем-то вроде вспомогательного класса? - person ; 21.05.2009