PHP RecursiveIteratorIterator:确定每个分支级别的第一个和最后一个项目

发布于 2024-10-06 09:17:10 字数 1446 浏览 4 评论 0原文

我扩展了 Zend_View_Helper_Navigation_Menu,它使用 RecursiveIteratorIterator 来迭代菜单树。我希望能够确定我是否位于树中分支级别的第一个或最后一个项目。

这是我正在寻找的示例:

  • Nav 1(第一个)
    • Nav 1.1(第一个和最后一个)
      • Nav 1.1.1(第一个)
      • 导航 1.1.2
      • Nav 1.1.3(最后)
  • 导航 2
    • Nav 2.1(第一)
    • Nav 2.2(最后)
  • 导航 3(最后一个)
    • Nav 3.1(第一)
    • Nav 3.2(最后)

其他信息

  • PHP 版本 5.2.13

解决方案

foreach 中($iterator as $page)< /code> 循环可以使用两个变量来跟踪深度:$depth$prevDepth。然后,一个简单的比较条件就可以确定分支级别中的第一项:if ($depth > $prevDepth)

使用 Zend_Navigation_Container 对象创建 RecursiveCachingIterator,然后使用该对象创建 RecursiveIteratorIterator 添加 hasNext() 方法。

$rci = new RecursiveCachingIterator($container, CachingIterator::FULL_CACHE);
$iterator = new RecursiveIteratorIterator($rci,
                    RecursiveIteratorIterator::SELF_FIRST);
/* snip */
$prevDepth = -1;
foreach ($iterator as $page) {
    $depth = $iterator->getDepth();
    /* snip */
    if ($depth > $prevDepth) {
        // first branch item
    }
    /* snip */
    if (!$iterator->hasNext()) {
        // last branch item
    }
    /* snip */
    $prevDepth = $depth;
}

I have extended Zend_View_Helper_Navigation_Menu, and it uses a RecursiveIteratorIterator to iterate over the menu tree. What I want to be able to determine is whether I am on the first or last item for a branch level in the tree.

Here's an example of what I'm looking for:

  • Nav 1 (first)
    • Nav 1.1 (first & last)
      • Nav 1.1.1 (first)
      • Nav 1.1.2
      • Nav 1.1.3 (last)
  • Nav 2
    • Nav 2.1 (first)
    • Nav 2.2 (last)
  • Nav 3 (last)
    • Nav 3.1 (first)
    • Nav 3.2 (last)

Additional Information

  • PHP Version 5.2.13

Solution

Within the foreach ($iterator as $page) loop two variables can be used to keep track of the depths, $depth and $prevDepth. A simple comparison conditional can then determine the first item in a branch level: if ($depth > $prevDepth).

Creating a RecursiveCachingIterator using the Zend_Navigation_Container object and then using that to create the RecursiveIteratorIterator adds the the hasNext() method.

$rci = new RecursiveCachingIterator($container, CachingIterator::FULL_CACHE);
$iterator = new RecursiveIteratorIterator($rci,
                    RecursiveIteratorIterator::SELF_FIRST);
/* snip */
$prevDepth = -1;
foreach ($iterator as $page) {
    $depth = $iterator->getDepth();
    /* snip */
    if ($depth > $prevDepth) {
        // first branch item
    }
    /* snip */
    if (!$iterator->hasNext()) {
        // last branch item
    }
    /* snip */
    $prevDepth = $depth;
}

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

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

发布评论

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

评论(2

箹锭⒈辈孓 2024-10-13 09:17:10

使用 RecursiveCachingIterator:

$rdi = new RecursiveDirectoryIterator('.');
$rci = new RecursiveCachingIterator($rdi, CachingIterator::FULL_CACHE); 
$rii = new RecursiveIteratorIterator($rci, RecursiveIteratorIterator::SELF_FIRST);

foreach ($rii as $file) {
    if ($file->isDir()) {
        echo $file->getFilename() . PHP_EOL;
    }
    elseif (!$rii->hasNext()) {
        echo $file->getFilename() . PHP_EOL;
    }
    elseif (count($rii->getCache()) == 1) {
        echo $file->getFilename() . PHP_EOL;
    }
}

另一种数组解决方案:

function buildTree(RecursiveDirectoryIterator $iterator) {
    $tree = array();
    foreach ($iterator as $fileinfo) {
        if ($fileinfo->isDir()) {
            $tree[$fileinfo->getFilename()] = buildTree($iterator->getChildren());
        } else {
            $tree[$fileinfo->getFilename()] = $fileinfo->getFilename();
        }
    }
    return $tree;
}

function filterTree(array $tree) {
    foreach ($tree as $key => $value) {
        if (is_array($value)) {
            $tree[$key] = filterTree($value);
        } elseif (reset($tree) !== $value && end($tree) !== $value) {
            unset($tree[$key]);
        }
    }
    return $tree;
}

print_r(filterTree(buildTree(new RecursiveDirectoryIterator('.'))));

Using RecursiveCachingIterator:

$rdi = new RecursiveDirectoryIterator('.');
$rci = new RecursiveCachingIterator($rdi, CachingIterator::FULL_CACHE); 
$rii = new RecursiveIteratorIterator($rci, RecursiveIteratorIterator::SELF_FIRST);

foreach ($rii as $file) {
    if ($file->isDir()) {
        echo $file->getFilename() . PHP_EOL;
    }
    elseif (!$rii->hasNext()) {
        echo $file->getFilename() . PHP_EOL;
    }
    elseif (count($rii->getCache()) == 1) {
        echo $file->getFilename() . PHP_EOL;
    }
}

Another solution with array:

function buildTree(RecursiveDirectoryIterator $iterator) {
    $tree = array();
    foreach ($iterator as $fileinfo) {
        if ($fileinfo->isDir()) {
            $tree[$fileinfo->getFilename()] = buildTree($iterator->getChildren());
        } else {
            $tree[$fileinfo->getFilename()] = $fileinfo->getFilename();
        }
    }
    return $tree;
}

function filterTree(array $tree) {
    foreach ($tree as $key => $value) {
        if (is_array($value)) {
            $tree[$key] = filterTree($value);
        } elseif (reset($tree) !== $value && end($tree) !== $value) {
            unset($tree[$key]);
        }
    }
    return $tree;
}

print_r(filterTree(buildTree(new RecursiveDirectoryIterator('.'))));
墨洒年华 2024-10-13 09:17:10

如果 $iterator 是一个密集数组,这可能会起作用:

// iterate container
$prevDepth = -1;
foreach ($iterator as $key => $page) {
    $depth = $iterator->getDepth();
    /* snip */
    if ($depth > $prevDepth) {
        // $page is first branch item

        if (isset($iterator[$key - 1])) {
            // $iterator[$key - 1] is last branch item in previous branch
        }
    }
    /* snip */
    $prevDepth = $depth;
}

您必须单独测试最后一项。

If $iterator is a dense array, this might work:

// iterate container
$prevDepth = -1;
foreach ($iterator as $key => $page) {
    $depth = $iterator->getDepth();
    /* snip */
    if ($depth > $prevDepth) {
        // $page is first branch item

        if (isset($iterator[$key - 1])) {
            // $iterator[$key - 1] is last branch item in previous branch
        }
    }
    /* snip */
    $prevDepth = $depth;
}

You will have to test for the very last item separately.

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