代码分离悖论:从多维数组创建 HTML 树并将 HTML 保留在递归函数之外

发布于 2024-07-21 10:51:10 字数 3044 浏览 7 评论 0原文

这个工作代码似乎是这个问题的典型解决方案。

它采用一个多维数组来保存类别及其子类别(对其深度没有隐含限制),并从中创建一个 HTML 无序列表,从递归函数内部将其回显到页面上。

通过从名为 _category_list()_ 的原始回调函数内部递归地将每个数组元素的“子”键的值传递给 array_walk() 来遍历子级别。

如何修改这种输出方法,以便所有 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 方法来构建树。 如果有办法避免使用该开关,我也愿意接受建议。

This working code seems to be the typical solution to this problem.

It takes a multi-dimensional array that holds categories and their subcategories (with no implied limitation on how many levels deep it goes) and creates an HTML unordered list from it, echoing it out onto the page from inside a recursive function.

Sub-levels are traversed by passing the value for each array element's 'children' key to array_walk() recursively, from inside the original callback function named _category_list()_.

How can this method of output be modified so that all HTML code would exist in the template, outside the function?

Here's the rundown of the code:

This multi-dimensional array holds the multi-level category tree.

Important keys to use in the HTML are 'category_id', 'name', and 'children'. Other keys have been purged from the array below for simplicity sake, but if they are useful they are: 'parent_id' and 'level' (starting with 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 (),
        ),
      ),
    ),
  ),
)

?>

.

This next function produces the majority of the HTML output, but it locks the HTML inside itself.

However, instead of echoing it right from the function, I'm looking for a way to pass this data back to the view template in a manner that is friendly for designers to customize.

<?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;
  }
}

?>

.

The next block of code is the current template html/php with the call to traverse the first level of the array via array_walk() and referencing the recursive function above. The function itself then handles the recursion and iteration of deeper categories with 1 or more child. Of course, this is the typical approach.

This code should have all HTML tags, rather than just the outer tags.

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

.

The Ideal Solution:

The end goal here is to find a way for template designers to create their ideal navigation structure without having to create or modify the recursion function (which isn't accessible), nor require use of a foreach loop for each level of the multi-dimensional array. The solution should not be tied to any specific depth limitations.

Examples of HTML customizations could range from placing additional attributes inside the ul/li tags, or even wrapping new tags around the output text, such as span tags, which are commonly used in navigations to achieve a sliding-doors effect with CSS. So I think the appropriate solution will need to support those case scenarios at a minimum.

Iterating through the array from the template using array_walk() would still be okay, as long as it can be used in such a way that the callback function passes the desired vars back to the template for use with the designer's HTML.

Ideally, if array_walk_recursive() knew how many levels deep its iterator actually is, I think this feat would be much easier to solve. But unless someone knows a workaround to that issue, the solution may be different entirely.

I also want to avoid using javascript methods of building the tree. And if there's a way to avoid using the switch, I'm open to suggestions there too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苍暮颜 2024-07-28 10:51:10

您是否想过编写一个类来管理和存储您想要传回的信息。 您的函数可以在该类的实例通过时改变它,并最终传回填充的对象。

您的内容将封装在类内,您可以编写所有方法和实用程序供用户操作和输出数据。 实用程序方法也可以在类中编写以显示级别数等。

我自己还没有尝试过,但这是我要开始的地方,因为该类允许我改进和扩展我的用户想要的东西,而他们不会不需要知道正在发生的事情的内部细节。

Have you thought of writing a Class that manages and stores the info you want to pass back. You function could alter an instance of that class as it goes though and in the end pass back the filled object.

Your content would be encapsulated inside the class and you can write all the methods and utilities for the user to manipulate and output the data. Utility methods can also be written inside the class to show the number of levels, etc.

I haven't tried it myself but this is where I would start since the Class allows me to refine and expand on what my users would want and they wouldn't need to know the internal details of what was happening.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文