【问题标题】:RecursiveIteratorIterator and RecursiveDirectoryIterator to nested html listsRecursiveIteratorIterator 和 RecursiveDirectoryIterator 到嵌套的 html 列表
【发布时间】:2012-06-02 12:28:12
【问题描述】:

这是我的 php 脚本:

<?php

$path = $_SERVER['DOCUMENT_ROOT'].'/test';

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);

foreach($objects as $name => $object){  
    echo  $objects->getDepth() . " " . $object->getFilename() . "<br/>";
    }

?>

这是脚本正在迭代的目录/文件树。 (它位于一个名为 $_SERVER['DOCUMENT_ROOT'].'/test' 的普通根目录中):

/food
/food/drinks
/food/drinks/water.html
/food/drinks/milk.html
/food/drinks/soda.html
/food/entrees
/food/entrees/hot
/food/entrees/hot/hamburger.html
/food/entrees/hot/pizza.html
/food/entrees/cold
/food/entrees/cold/icecream.html
/food/entrees/cold/salad.html
/cosmetics
/cosmetics/perfume
/cosmetics/perfume/chic.html
/cosmetics/perfume/polo.html
/cosmetics/perfume/lust.html
/cosmetics/lipstick
/cosmetics/lipstick/colors
/cosmetics/lipstick/colors/red.html
/cosmetics/lipstick/colors/pink.html
/cosmetics/lipstick/colors/purple.html

这是脚本输出的内容:

0 food
1 drinks
2 milk.html
2 water.html
2 soda.html
1 info.php
1 entrees
2 hot
3 pizza.html
3 hamburger.html
2 cold
3 ice_cream.html
3 salad.html
0 cosmetics
1 lipstick
2 colors
3 pink.html
3 red.html
3 purple.html
1 perfume
2 polo.html
2 lust.html
2 chic.html
0 error_log
0 test.php

忽略 $objects->getDepth() 整数;仅供参考

问题:如何修改我的脚本以输出嵌套的无序列表,如下所示:

<ul>
  <li>food</li>
    <ul>
      <li>drinks</li>
        <ul>
          <li>water.html</li>
          <li>milk.html</li>
          <li>soda.html</li>
        </ul>
      <li>entrees</li>
        <ul>
          <li>hot</li>
            <ul>
              <li>hamburger.html</li>
              <li>pizza.html</li>
            </ul>
          <li>cold</li>
            <ul>
              <li>icecream.html</li>
              <li>salad.html</li>
            </ul>      
        </ul>
    </ul>
  <li>cosmetics</li>
    <ul>
      <li>perfume</li>
        <ul>
          <li>chic.html</li>
          <li>polo.html</li>
          <li>lust.html</li>
        </ul>
      <li>lipstick</li>
        <ul>
          <li>colors</li>
            <ul>

谢谢!

【问题讨论】:

    标签: php recursion iterator html-lists


    【解决方案1】:

    这是一个使用 DomDocument 的例子

    基本思想是每个目录的内容用&lt;ul&gt;表示,目录中的每个元素用&lt;li&gt;表示
    如果元素是一个非空目录,它将包含一个&lt;ul&gt; 来表示它的内容等等。

    $path = $_SERVER['DOCUMENT_ROOT'].'/test';
    $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
    $dom = new DomDocument("1.0");
    $list = $dom->createElement("ul");
    $dom->appendChild($list);
    $node = $list;
    $depth = 0;
    foreach($objects as $name => $object){  
        if ($objects->getDepth() == $depth){
    //the depth hasnt changed so just add another li
            $li = $dom->createElement('li', $object->getFilename());
            $node->appendChild($li);
        }
        elseif ($objects->getDepth() > $depth){
    //the depth increased, the last li is a non-empty folder 
            $li = $node->lastChild;
            $ul = $dom->createElement('ul');
            $li->appendChild($ul);
            $ul->appendChild($dom->createElement('li', $object->getFilename()));
            $node = $ul;
        }
        else{
    //the depth decreased, going up $difference directories
            $difference = $depth - $objects->getDepth();
            for ($i = 0; $i < $difference; $difference--){
                $node = $node->parentNode->parentNode;
            }
            $li = $dom->createElement('li', $object->getFilename());
            $node->appendChild($li);
        }
        $depth = $objects->getDepth();
    }
    echo $dom->saveHtml();
    

    输出将沿线

    <ul>
        <li>dir1</li>
        <li>dir2
            <ul>
                <li>in dir2</li>
            <ul>
        <li>file in root</li>
    <ul> 
    

    【讨论】:

    • 是的!这完美地做到了!谢谢
    【解决方案2】:

    将深度存储在一个变量中,并检查每个循环该变量是否增加或减少?

    如果深度增加,则添加另一个&lt;ul&gt; 标签,如果深度减少,则添加结束&lt;/ul&gt; 标签。

    每个循环都会输出&lt;li&gt;标签来包装文件名。

    例如

    $depth = 0;
    foreach ($objects as $name => $object) {
        $depth2 = $objects->getDepth();
        if($depth2 > $depth) { echo '<ul>'; }
        echo "<li>" . $object->getFilename() . "</li>";
        if($depth2 < $depth) { echo '</ul>'; }
        $depth = $depth2;
    }
    

    这需要一些额外的测试和修改以适应您现有的代码,但希望它能给您一些想法。

    【讨论】:

    • 这需要放多个标签,如果最后一个$object是深度3,下一个对象是深度1,例如:
    • 例如,如果最后一个 $object 的深度为 3(如沙拉.html),而下一个 $object 的深度为 0(如“化妆品”),那么我们必须回显 在
    • 之前。即,更高深度的 UL 必须完全关闭。
  • @user743094:您只需将if 替换为循环即可。 while($depth2 &lt; $depth) { echo '&lt;/ul&gt;'; $depth--; 或类似的东西。
  • 猜你喜欢
    相关资源
    最近更新 更多
    热门标签