Cmlap Hírek, cikkek Multilevel ul menü létrehozása adatbázisból

Multilevel ul menü létrehozása adatbázisból

A menüket, vagy kategória menüket általában nem kézzel hozzuk létre, hanem adatbázisban tároljuk. A tárolásnál egészen biztosan bejegyzésre kerül egy azonosító a menühöz, a szülõ azonosítója, a felirat és esetleg az url.

Ebben a példában a CakePHP TreeBehavior használatával fogjuk létrehozni a többszintû listából készített menüszerkezetet, méghozzá úgy, hogy meg is jelöljük azokat a menüket, amelyeknek van gyermeke!

A lekérdezés sokkal gyorsabb, ha nem rekurzívan, hanem egy egyszerû listába kérjük az eredményt oly módon, hogy szülõ szerint rendezünk!
Ez a felépítés nem csak CakePHP-ban mûködik, anélkül is teljesen ugyanígy lehet megoldani.

A "kategória fa" (ami most kategória lista) feldolgozása szekvenciálisan fog történni verem használatával, hogy gyorsabb legyen a lekérdezés és a kiprintelés is! Ha egymásba ágyazott rekurzív tömböt ( Cake-ben threaded ) használnánk, a megjelenítés és az adatok elõállítása is rekurzívan történne, ami felesleges ha anélkül is megoldható.

1. Készítsük el az adatbázisszerkezetet (lásd: Tree)! Kiegészítettem egy url mezõvel, mivel majd valamit akarunk kezdeni a kategóriával.
CREATE TABLE categories (
    id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    parent_id INTEGER(10) DEFAULT NULL,
    lft INTEGER(10) DEFAULT NULL,
    rght INTEGER(10) DEFAULT NULL,
    name VARCHAR(255) DEFAULT '',
url VARCHAR(255) DEFAULT '',
 PRIMARY KEY (id) );


2. Készítsük el a modellt. Az app/Model könyvtárban hozzuk létre a Category.php fájlt a következõ tartalommal:

<?php
class Category extends AppModel {
    //ezzel mondjuk meg a CakePHP-nek, hogy ezt a modellt (táblát) fa-ként használja
    public $actsAs = array('Tree');
   
}

//Hozzuk létre azt a modellt is ami majd használja a kategóriáinkat, mondjuk Item.php néven ugyanúgy a modellben
<?php
class Item extends AppModel {
    public $belongsTo=array('Category');
}

3. A menü View létrehozása, ami most egy Element, így készítsünk egy fájlt, mondjuk category_menu.ctp néven az app/View/Elements könyvtáron belül, így bárhonnan használható. A tartalma a következõ legyen:


<?php
    App::import('Model','Category');
    $categories=new Category();
    $category=$categories->children();//sima lista lekérése

    //ebbe a verembe kerül, hogy megkeztünk egy olyan ágat aminek gyereke van
    $stack=array();

    for($i=0;$i<count($category);$i++){
        $row=$category[$i];
        //elõre nézünk a listában
        $nextrow=(isset($category[$i+1]))?$category[$i+1]:null;

        $id=$row['Category']['id'];
        //a listában következõ elem szülõjét eltesszük ha van, mert ezt fogjuk összehasonlítani a saját id-nkel
        $childparent=($nextrow)?$nextrow['Category']['parent_id']:null;
        $url='/items/showCategory/'.$row['Category']['url'];

        //ha az id-nk egyezik az elsõ gyerek szülõjével, akkor meg kell nyitni az ul-t, és el kell tenni a stackbe a nyitást
        if($id==$childparent){
            array_push($stack, $id);
            ?>

                      <li class="dropdown"> <a href="<?php echo $url; ?>"> <?php echo $row['Category']['name']; ?> <span class="right-arrow"></span> </a>
                          <ul class="clearfix">

            <?php
        //ha van nyitás és a következõ elem szülõje már nem egyezik az utolsó eltett szülõvel, akkor zárni kell, de elõtte printeljük ki az adott menüpontot is
        }elseif(!empty($stack) && $stack[count($stack)-1]!=$childparent){
            ?>
                <li> <a href="<?php echo $url; ?>"> <?php echo $row['Category']['name']; ?> </a> </li>
            <?php
            //addig ürítjük a vermet és tesszük a lezárásokat, míg a verem ki nem ürül, vagy újra a kinyitott szintre nem kerülünk
            while(!empty($stack) && $stack[count($stack)-1]!=$childparent){
                array_pop($stack);
                ?>

                          </ul>
                     </li>

                <?php
            }
        //ha egyik feltétel sem teljesül, akkor csak sima menüpontok ( li elemek ) kerülnek kiírásra
        }else{
            ?>

                <li> <a href="<?php echo $url; ?>"> <?php echo $row['Category']['name']; ?> </a> </li>

            <?php
        }
            ?>

<?php       
    }
?>



4. Használjuk fel a menünket valamelyik view-ban, mondjuk az oldalban. Alapértelmezetten az app/View/Layouts/default.ctp fájlban. Illesszük be a megfelelõ helyre a következõ tartalmat:

<?php echo $this->element('category_menu');?>


5. Csináljunk valamit amikor valaki a menüre kattint. Hozzuk létre a kontrollert. Készítsünk egy ItemsController.php nevû fájlt az app/Controller könyvtárban a következõ tartalommal:

<?php
class ItemsController extends AppController {
    public $components=array('Paginator');
    public $uses=array('Item','Category');

    public function showCategory($catUrl){
         $this->paginate=array(
             ..........
         );
    }

}




Természetesen rengeteg más megoldás is mûködik, ez csak egy példa, hogyan lehet egészen egyszerûen megoldani egy viszonylag nehezebb feladatot.

CakePHP nélkül:
  • a táblaszerkezet akár ugyanilyen is lehet
  • a lekérdezés: select * from categories group by parent_id,id order by lft asc;
  • a megjelenítésnél pedig nyilván a cake-es cuccokat hagyjuk ki!




Ha tetszett vagy hasznosnak talltad, krlek oszd meg!
Author / szerz:
Hozzszlsok
Vlasszon nyelvet!
Keress a tartalomban
Kattintson ide az adatok elkldshez!