Çok-boyutlu bir dizi gezinti Oluştur

8 Cevap php

The question: How do I generate navigation, allowing for applying different classes to different sub-items, from a multi-dimensional array?

Burada çok düzeyli navigasyon için herhangi bir ihtiyaç vardı önce bunu yaptığını nasıl:

Home 
Pics 
About

ve nav arayarak oluşturulan ():

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

İşte buildLinks () 'dir:

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

My question, again:

nasıl aşağıdaki nav ulaşmak (ve görünür alt gezinme öğeleri zaman bu özel sayfada sadece mevcut olduğunu fark olur):

Home
    something1
    something2 
Pics 
About

ve ...

Home
Pics
    people
    places 
About

What I've tried

Ona bakarak bu SPL bazı yineleyici bunun için iyi bir uyum olacağını görünüyor ama bu yaklaşım nasıl emin değilim. Ben RecursiveIteratorIterator ile yaklaşık oynadı ama doğru sayfada olup olmadığını sadece bu öğeleri göstermek için nasıl da sadece alt menü öğeleri ve farklı bir stil uygulamak için nasıl emin değilim.

Ben test etmek için ama tek SubMenu1 öğeleri ile çalışmak nasıl bilmiyorum bu dizi inşa:

$nav = array(
array(
"Home" => "home.php",
"submenu1" => array(
    "something1"=>"something1.php",
    "something2" => "something2.php")
),
array("Pics" => "pics.php"),
array("About" => "about.php")
);

Aşağıdaki sırayla sürü çıktı ama nasıl başvurabilirim, bir sınıf adı SubMenu1 öğeleri söylemek ya da kişi "Ana" sayfa, diyelim ki, üzerinde yalnızca onlara göstermek?

$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($nav));

foreach($iterator as $key=>$value) {
    echo $key.' -- '.$value.'<br />';
}

Ve bu beni alır:

Home
something1
something2
Pics
About

Ama ben sadece bu unsurları nasıl hedef görmüyorum çünkü o alt kalemleri ve sadece şartlı bunları görüntülemek için hiçbir şekilde sınıfları uygulamak için hiçbir yolu yoktur.

8 Cevap

Sen RecursiveIteratorIterator ile doğru yolda idi. Bu aslında bir özyinelemeli yineleyici düzleştirir. İşte doğru yolu:

$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";
}

verir

Home => home.php
submenu1 => Array
    something1 => something1.php
    something2 => something2.php
Pics => pics.php
About => about.php

, Tekerleği yeniden icat Zend_Navigation kullanmak ve mutlu olacaktır etmeyin.

It seems like you might want to do this in a more object oriented way. If not, it seems like you should at least define an algorithm that makes sense, right now you are just blindly guessing. Instead, DEFINE.

Örneğin:

Ben bir php tabanlı karma ağaç olmak benim navigasyon tanımlama. Bir navigasyon öğesi şu olacaktır:

Bir üst düzey bağlantı varsa A), dizi karma "navigasyon yaprak" etiketli bir öğe (alt dizi) içerecektir

b) Bir navigasyon Yaprak "Gösterge değeri", "bağlantısını değer" ve "alt değer" etiketli unsurları içerecektir. Bu ürünler bir çapa etiketi oluşturmak için kullanılacaktır.

Bir eleman bir alt menüsü varsa c), bir "Navigasyon Leaf" içeren ek olarak, bir "alt gezinti" eleman mevcut olacaktır. Bir görüntülenebilen navigasyon öğe varsa bir alt gezinti elemanı "Navigasyon Leaf" sahip olacaktır.

Daha sonra seçtiğiniz tanımına dayalı navigasyon gösterecektir işlevleri / yöntemleri yazabilirsiniz.

Ben ne yapardım, bu çizgisinde bir şeydir:

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

Sonra tüm bir dizi ... menü oluşturmak için kök menü öğeleri bir koleksiyon, sadece yapın:

$rootItems = array($item1, $item2);
$out = '<ul>';
foreach ($rootItems as $item) {
    $out .= (string) $item;
}
$out .= '</ul>';

Ben kullanıcı vb, nesneyi inşa çocukları ekleyerek semantik bırakacağım ...

Ne gelecek şekilde yeniden yazma nav fonksiyonu hakkında:

function nav($links, $level){       
    foreach($links as $k => $v) {
        if (is_array($v)) {
            nav($v, $level + 1)
        } else {
            echo buildLinks($k, $v, $base);
        }
    }
}

Ve daha diyoruz:

$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);

Basit yolu, IMHO, sadece bir özyinelemeli arama yapmak, ve (bu, iç içe diziler olduğu) navigasyon bir ağaç yapılandırılmış açıklama kullanmaktır. Denenmemiş bir örnek kod:

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

Ben bu yazıyı okumak gerektiğini düşünüyorum!

bu yardım umut!

@ Catchmeifyoutry

Eğer LoL benim hayatımı kurtardı, teşekkür ederiz.

Ben senin fonksiyon benim kullanımı uyarlamak için biraz değişti ve bu çıktı:

$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";
}

Thank you very much!

Ben sayfa hız tho kod bu tür var ne kadar etkisi merak ediyorum. Milisaniye birkaç mikrosaniye: D