PHP ve MySQL ile menü sınırsız düzeyde inşa etmek nasıl

6 Cevap php

Eh, benim menü benim menü oluşturmak için böyle bir db benzer yapısını kullanmak

  2  Services                  0
  3  Photo Gallery             0
  4  Home                      0
  5  Feedback                  0
  6  FAQs                      0
  7  News & Events             0
  8  Testimonials              0
 81  FACN                      0
 83  Organisation Structure   81
 84  Constitution             81
 85  Council                  81
 86  IFAWPCA                  81
 87  Services                 81
 88  Publications             81

To assign another submenu for existing submenu I simply assign its parent's id as its value of parent field. parent 0 means top menu

Başka bir alt menü içinde alt menüyü oluştururken şimdi sorun yok

şimdi bu ben üst menü için alt menü getirme yoludur

<ul class="topmenu">
    <? $list = $obj -> childmenu($parentid); 
        //this list contains the array of submenu under $parendid
        foreach($list as $menu) {
            extract($menu);
            echo '<li><a href="#">'.$name.'</a></li>';
        }
    ?>
</ul>

Ne yapmak istiyorum.

Ben yeni bir menü diğer çocuk menüsü olup olmadığını kontrol etmek istiyorum

ve bunu kullanılabilir her alt menü arar kadar kontrol devam etmek istiyorum

ve ben bu gibi onun belirli liste öğesi içinde alt menüsünü görüntülemek istiyorum

<ul>       
       <li><a href="#">Home</a>
        <ul class="submenu">
           ........ <!-- Its sub menu -->
           </ul>
       </li>
</ul>

6 Cevap

Bunun için özyinelemeli işlevleri kullanmak gerekir. Technically, there's a few ways to do it, but recursion is really the best option here.

İşte işe nasıl temel özü budur:

function drawMenu ($listOfItems) {
    echo "<ul>";
    foreach ($listOfItems as $item) {
        echo "<li>" . $item->name;
        if ($item->hasChildren()) {
            drawMenu($item->getChildren()); // here is the recursion
        }
        echo "</li>";
    }
    echo "</ul>";
}

Özellikleri ve yöntemleri $item sadece örnektir, ve sana gereken, ancak bu uygulamak için size bırakacağım, ama genelinde mesajı alır düşünüyorum.

Sizinki gibi bir veritabanı yapısı ile, a single query ve without recursion ile tüm HTML menü oluşturmak mümkündür.

Evet - Ben tekrar edecektir:

  • BİR SORGU
  • Yinelemesiz

Bu her zaman kendim de kullanıyorum yaklaşımdır.

Burada kodu kopyaladım - tam fonksiyonlu:

http://pastebin.com/GAFvSew4

Ilginç bölümünü ("get_menu_html") görmek için hattına 67 atlamak.

Ana döngü hat 85 başlar.

Beş "özelleştirilebilir" HTML parçacıkları vardır:

  1. menü sarıcı açılış (line 83)
  2. menü sarıcı kapanış (line 122)
  3. Menü oğul açılması (line 100) ile item
  4. oğul kapanış ile menü öğesi (line 92)
  5. oğul olmadan menü öğesi (line 113)

(I tabulation ile endişeli olsaydı kod temiz olabilir.)

Oluşturmak ve örnek veritabanı doldurmak için SQL komut sonunda mevcuttur.

Bunu deneyin ve bize düşüncelerinizi bildirebilirsiniz.

İşte bu sorun için "one query, no recursion" çözümün bir "geliştirici-dostu" sürümüdür.

SQL:

SELECT id, parent_id, title, link, position FROM menu_item ORDER BY parent_id, position;

PHP:

$html = '';
$parent = 0;
$parent_stack = array();

// $items contains the results of the SQL query
$children = array();
foreach ( $items as $item )
    $children[$item['parent_id']][] = $item;

while ( ( $option = each( $children[$parent] ) ) || ( $parent > 0 ) )
{
    if ( !empty( $option ) )
    {
        // 1) The item contains children:
        // store current parent in the stack, and update current parent
        if ( !empty( $children[$option['value']['id']] ) )
        {
            $html .= '<li>' . $option['value']['title'] . '</li>';
            $html .= '<ul>'; 
            array_push( $parent_stack, $parent );
            $parent = $option['value']['id'];
        }
        // 2) The item does not contain children
        else
            $html .= '<li>' . $option['value']['title'] . '</li>';
    }
    // 3) Current parent has no more children:
    // jump back to the previous menu level
    else
    {
        $html .= '</ul>';
        $parent = array_pop( $parent_stack );
    }
}

// At this point, the HTML is already built
echo $html;

Sadece $ parent_stack değişkenin kullanımını anlamak gerekir.

Bu (Son olarak, First Out) bir "LIFO" yığını - Wikipedia makalesinde resim bin kelime değerlerinizi: http://en.wikipedia.org/wiki/LIFO_%28computing%29

Bir menü seçeneği alt seçenekleri vardır, biz yığını üst kimliğini saklamak:

array_push( $parent_stack, $parent );

Ve sonra, biz hemen geçerli menü seçeneği kimliği olacak yapma, $ parent güncelleme:

$parent = $option['value']['id'];

Biz tüm alt seçenekleri döngüye sonra, önceki seviyesine geri dönebilirsiniz:

$parent = array_pop( $parent_stack );

Biz yığını üst kimliği saklı nedeni budur!

Benim öneri: Yukarıdaki kod parçacığını düşünmek ve anlamak.

Sorular bekliyoruz!

Ben bu yaklaşımda görmek avantajlarından biri de özyineleme kullanıldığında olabilir sonsuz bir döngü içine girme riskini ortadan kaldırır olduğunu.

Ben ön sipariş ağaç geçişi içine bakmak öneririm. De konuyla ilgili bir makale var:

Managing Hierarchical Data in MySQL

Etkili, bir 'düğüm' olarak her sayfayı alır. Her düğüm o ebeveynine bir başvuru var. Eğer (vb, düğümleri hareket, bir çocuk eklemek) düğümlerin düzenini değiştirdiğinizde, (Yukarıdaki makale php kaynak kodu bağlantıları olan, çok detaylı olarak bu açıklar her düğüm için bir 'sol' ve 'sağ' değerini yeniden hesaplamak .) Ne ile sonuna kadar çok hızlı verilen bir düğüm herhangi bir başka düğümün doğrudan veya dolaylı bir çocuk olup olmadığını belirlemek, hem de belirli bir düğümün tüm alt düğümlerini almak için yeteneğidir.

i tekrarlamalı bir fonksiyon kullanmak istiyorsunuz.

ben bu kodu gibi tam değil biliyorum, ama özyineleme anlamak eğer genel kavram alabilirsiniz düşünüyorum. Eğer özyineleme çek anlamıyorum eğer http://en.wikipedia.org/wiki/Recursion_(computer_science)

$list = new List();

function print_menu($list) {

    echo '<ul>';
    foreach($list as $item) {
        echo '<li><a href="#">' . $item->name . '</a>';
        if($item->has_child) {
            print_menu($item);
        }
        echo '</li>';
    }
    echo '</ul>';
}

http://pastebin.com/ariBn3pE

Sen özyineleme kullanmanız gerekir, ama benim yaklaşım o zaman düzeyleri, ve sonra tüm nesneleri birleştirme ki örgütlü, ebeveynlerine göre sonuçlar ve grup için bireysel nesne her unsurları sorgulandığında, ben tek tek her menü işlemek için bir sınıf oluşturduk, farklı birine ... tam kodu için pastebin kontrol