问题:如何生成导航,允许从多维数组中将不同的类应用于不同的子项?
在我需要多级导航之前,我就是这样做的:
Home
Pics
About
并通过调用nav()生成:
function nav(){
$links = array(
"Home" => "home.php",
"Pics" => "pics.php",
"About" => "about.php"
);
$base = basename($_SERVER['PHP_SELF']);
foreach($nav as $k => $v){
echo buildLinks($k, $v, $base);
}
}
这是buildLinks():
function buildLinks($name, $page, $selected){
if($selected == $page){
$theLink = "<li class=\"selected\"><a href=\"$page\">$name</a></li>\n";
} else {
$thelink = "<li><a href=\"$page\">$name</a></li>\n";
}
return $thelink;
}
我的问题,再次:
我如何实现以下导航(并注意到可见的子导航元素仅在该特定页面上出现时):
Home
something1
something2
Pics
About
和...
Home
Pics
people
places
About
我尝试了什么
从它看来,似乎SPL中的某些迭代器很适合这个,但我不知道如何处理它。我玩过RecursiveIteratorIterator,但我不知道如何将不同的样式仅应用于子菜单项,以及如果只在正确的页面上显示这些项目。
我构建了这个数组以进行测试但不知道如何单独使用子菜单项:
$nav = array(
array(
"Home" => "home.php",
"submenu1" => array(
"something1"=>"something1.php",
"something2" => "something2.php")
),
array("Pics" => "pics.php"),
array("About" => "about.php")
);
以下内容将按顺序打印出来,但我如何申请,比如将一个类别名称应用于子菜单项目,或者仅在该人员开启时显示它们,例如“主页”页面?
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($nav));
foreach($iterator as $key=>$value) {
echo $key.' -- '.$value.'<br />';
}
这让我:
Home
something1
something2
Pics
About
但我无法将类应用于这些子项,也无法只是有条件地显示它们,因为我看不到如何仅仅针对这些元素。
答案 0 :(得分:3)
不要重新发明轮子,使用Zend_Navigation,你会很高兴。
答案 1 :(得分:1)
似乎您可能希望以更面向对象的方式执行此操作。 如果没有,似乎你应该至少定义一个有意义的算法,现在你只是盲目地猜测。相反,DEFINE。
例如:
我将导航定义为基于php散列的树。导航项将具有以下内容:
A)如果有顶级链接,则数组哈希将包含标记为“navigation leaf”的项(子数组)
b)导航Leaf将包含标记为“显示值”,“链接值”和“alt值”的元素。这些项目将用于生成锚标记。
c)如果元素具有子菜单,除了包含“导航叶”之外,还将存在“子导航”元素。如果子导航元素具有可显示的导航项,则它将具有“导航叶”。
然后,您可以编写将根据您选择的定义显示导航的功能/方法。
答案 2 :(得分:1)
我会做的是这样的事情:
class MenuItem {
protected $active = false;
protected $children = array();
protected $name = '';
protected $link = '';
public function __construct($name, $link, $active) {}
public function __toString() {
//render this item
$out = ''; #render here
if (!$this->isActive()) {
return $out;
}
$out .= '<ul>';
foreach ($this->children as $child) {
$out .= (string) $child;
}
$out .= '</ul>';
return $out;
}
public function isActive() {
if ($this->active) {
return true;
}
foreach ($this->children as $child) {
if ($child->isActive()) {
return true;
}
}
return false;
}
}
然后,您拥有的只是数组中的根菜单项的集合...要构建菜单,您只需:
$rootItems = array($item1, $item2);
$out = '<ul>';
foreach ($rootItems as $item) {
$out .= (string) $item;
}
$out .= '</ul>';
我将保留构造对象,向用户添加子等等的语义......
答案 3 :(得分:1)
如何以下一种方式重写导航功能:
function nav($links, $level){
foreach($links as $k => $v) {
if (is_array($v)) {
nav($v, $level + 1)
} else {
echo buildLinks($k, $v, $base);
}
}
}
而不是称之为:
$links = array(
array(
"Home" => "home.php",
"submenu1" => array(
"something1"=>"something1.php",
"something2" => "something2.php")
),
array("Pics" => "pics.php"),
array("About" => "about.php")
);
nav($links, 0);
答案 4 :(得分:1)
最简单的方法,恕我直言,只是进行递归调用,并使用导航的树结构描述(即嵌套数组)。未经测试的示例代码:
<?php
$links = array(
"Home" => array("home.php", array(
"something1"=> array("something1.php", array()),
"hello"=> array("hello.php", array(
"world" => array("world.php", array()),
"bar" => array("bar.php", array()),
)),
)),
"Pics" => array("pics.php", array(
"people"=>"people.php",
"places" => "places.php",
)),
"About" => array("about.php", array()), // example no subitems
);
// use the following $path variable to indicate the current navigational position
$path = array(); // expand nothing
$path = array('Home'); // expand Home
$path = array('Home', 'hello'); // also expand hello in Home
// map indent levels to classes
$classes = array(
'item',
'subitem',
'subsubitem',
);
// recursive function to build navigation list
function buildNav($links, $path, $classes)
{
// selected page at current level
// NOTE: array_shift returns NULL if $path is empty.
// it also alters the array itself
$selected = array_shift($path);
$class = array_shift($classes);
echo "<ul>\n";
foreach($links as $name => $link)
{
list($href, $sublinks) = $link;
if ($name == $selected)
{
echo "<li class=\"selected $class\"><a href=\"$href\">$name</a>\n";
// recursively show subitems
// NOTE: path starts now with the selected subitem
buildNav($sublinks, $path, $classes);
echo "</li>\n";
}
else
{
echo "<li><a href=\"$href\" class=\"$class\">$name</a></li>\n";
}
}
echo "<ul>\n";
}
// actually build the navigation
buildNav($links, $path, $classes);
?>
答案 5 :(得分:1)
你使用RecursiveIteratorIterator走在正确的轨道上。它基本上使递归迭代器变平。这是正确的方法:
$nav = array(
array(
"Home" => "home.php",
"submenu1" => array(
"something1"=>"something1.php",
"something2" => "something2.php")
),
array("Pics" => "pics.php"),
array("About" => "about.php"),
);
$it = new RecursiveIteratorIterator(
new RecursiveArrayIterator($nav),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($it as $k => $v) {
if ($it->getDepth() == 0)
continue;
echo str_repeat(" ", $it->getDepth() - 1) .
"$k => $v\n";
}
给出
Home => home.php
submenu1 => Array
something1 => something1.php
something2 => something2.php
Pics => pics.php
About => about.php
答案 6 :(得分:1)
@catchmeifyoutry
谢谢,你救了我的生命。
我稍微改变了你的功能以适应我的使用,这就出现了:
$html['navi'] = array(
"Home" => "/home/",
"DJs & Shows" => "/djs-shows/",
"Playlists" => "/playlists/",
"Newsbeat" => "/newsbeat/",
"Reviews" => "/reviews/",
"TV" => "/tv/",
"Contact" => "/contact/",
"Test" => array("/test/",
array("Submenu 1" => "/test/link1",
"Submenu 2" => "/test/link2",
"Submenu 3" => "/test/link3",
"Submenu 4" => "/test/link4",
"Submenu 5" => "/test/link5",
"Submenu 6" => "/test/link6"
)
)
);
$classes = array(
'first-level',
'second-level',
'third-level',
);
function siteNavi($links, $classes) {
// The best way for MultiArray navigation (LOVE IT!)
// Array Shift selects first element and removes it from array
$class = array_shift($classes);
echo "<ul class=\"$class\">\n";
foreach($links as $name => $link) {
if (is_array($link) AND $class != "") {
list($link, $sublinks) = $link;
if ($_GET['site'] == basename($link)) { $selected = ' class="current"'; } else { $selected = ""; }
echo "<li{$selected}><a href=\"{$link}\">{$name}</a>\n";
// recursively show subitems
// NOTE: path starts now with the selected subitem
siteNavi($sublinks, $classes);
echo "</li>\n";
} else {
if ($_GET['site'] == basename($link)) { $selected = ' class="current"'; } else { $selected = ""; }
echo "<li{$selected}><a href=\"{$link}\" >{$name}</a></li>\n";
}
}
echo "</ul>\n";
}
非常感谢!
我想知道这种代码对页面速度有多大影响。几微秒毫秒:D