Парадокс разделения кода: создание HTML-дерева из многомерного массива и сохранение HTML вне рекурсивной функции - PullRequest
2 голосов
/ 21 мая 2009

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

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

Подуровни просматриваются путем рекурсивной передачи значения ключа 'children' каждого элемента массива изнутри исходной функции обратного вызова с именем _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 для построения дерева. И если есть способ избежать использования переключателя, я тоже открыт для предложений.

1 Ответ

1 голос
/ 21 мая 2009

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

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

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

...