Chceme mít kategorii, která má podkategorii a možnost aby každá podkategorie mohla mít další podkategorie.
Pracuji na jedné php aplikaci a potřeboval jsem generovat kategorie a podkategorii, ale tak aby každá podkategorie mohla mít svou další podkategorii. Ukáži Vám část svého řešení. Rozšířené funkce zde neuvádím, ale pouze základní kostru.Struktura tabulky
Předpokládám, že každá podkategorie má svoji nadkategorii a ta má opět svoji nadkategorii. Aneb každý syn má svého otce, a každý otec má svého otce.... Ale narozdíl od přírody, zde musí být nějaký táta všech tátů. Takového jsem v tabulce označil hodnotou NULA. Což znamená, že je to nejvyšší kategorie.
CREATE TABLE `kat` (
`id` int(11) NOT NULL auto_increment,
`nazev` varchar(250) NOT NULL,
`tata` int(11) NOT NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM;
INSERT INTO `kat` VALUES (1, 'PC', 0);
INSERT INTO `kat` VALUES (2, 'notebooky', 1);
INSERT INTO `kat` VALUES (3, 'monitory', 1);
INSERT INTO `kat` VALUES (4, 'média', 0);
INSERT INTO `kat` VALUES (5, 'ACER', 2);
INSERT INTO `kat` VALUES (6, 'DELL', 2);
INSERT INTO `kat` VALUES (7, 'ACER - komponenty', 5);
INSERT INTO `kat` VALUES (8, 'klávesnice', 1);
INSERT INTO `kat` VALUES (9, 'normální monitory', 3);
INSERT INTO `kat` VALUES (10, 'LCD', 3);
INSERT INTO `kat` VALUES (11, 'bílé klávesnice', 8);
INSERT INTO `kat` VALUES (12, 'černé klávesnice', 8);
Tabulka bude vypadat následovně
id | nazev | tata |
1 | PC | 0 |
2 | notebooky | 1 |
3 | monitory | 1 |
4 | média | 0 |
5 | ACER | 2 |
6 | DELL | 2 |
7 | ACER - komponenty | 5 |
8 | klávesnice | 1 |
9 | normální monitory | 3 |
10 | LCD | 3 |
11 | bílé klávesnice | 8 |
12 | černé klávesnice | 8 |
Ukázka jak to bude fungovat
Otevřete si PŘÍKLAD, a klikněte na PC - notebooky - ACER. Budou se rozbalovat jednotlivé podkategorie. PC a média mají TATU=0, což znamená, že to jsou kategorii, které nemají svého rodiče (nadkategorii). Při kliknutí na PC, se začnou hledat takové prvky, které mají TATA=1 (protože id od kategorie PC=1), nacházíme notebooky, monitory a klávesnice. Při stisku notebooky, hledá to prvky, které mají TATA=2 (protože id notebooky je 2) a nakonec klikáme na ACER, a hledáme prvky které mají TATA=5, a poté již končíme, protože to je poslední podkategorie (neboli, nemají svého syna :-) ).Soubor fce/kat.php
V adresáři fce vytvořte soubor kat.php
<?
function posloupnost_k_obsahu($tata)
{
$maximum_urovni=100; // ochrana proti zacykleni
do
{
$dotaz_na_tatu = "SELECT id,tata FROM `kat` WHERE id=$tata LIMIT 1"; //info o prvku
$nacti_tatu = mysql_query($dotaz_na_tatu);
$tata = MySQL_Fetch_Array($nacti_tatu);
$id = $tata["id"];
$tata = $tata["tata"]; //nadrazeny prvek,neboli tata
if ($id > 0)
$strom[]=$id; // pridame prvek do stromu
$urovni++;
}
while ( ($tata != 0) and ($urovni < $maximum_urovni));
//to neni nejvyssi prvek, coz znamena ze tata by byl roven nule
//anebo jsme se nezacyklili, muzeme pokracovat
$strom[]=0; //pridame na konec nulty prvek, tatu vsech tatu :-)
return array_reverse($strom); //a otocime
}
function mezera($velikost)
{
$velikost=$velikost*1;
$mezera="";
for ($i=0;$i<=$velikost;$i++) $mezera = $mezera." ";
return $mezera;
}
function vypis($kdo,$strom)
//potrebujem strom, ktery urci cestu k aktualni kategorii
{
if ( count($strom)==($kdo+1) )
//je to posledni prvek, tedy budeme jej rozbalovat a skoncime
{
$posledni = count($strom)-1;
$dotaz_na_polozku[$kdo] = "SELECT * FROM `kat` WHERE tata=$strom[$posledni]";
}
else
$dotaz_na_polozku[$kdo] = "SELECT * FROM `kat` WHERE tata=$strom[$kdo]";
// bezny prvek, vypiseme vsechny prvky z teto urovne
$nacti_polozku[$kdo] = mysql_query($dotaz_na_polozku[$kdo]);
while ($polozka[$kdo] = MySQL_Fetch_Array($nacti_polozku[$kdo]))
{
$nazev_p = $polozka[$kdo]["nazev"];
$id_p = $polozka[$kdo]["id"];
$tata_p = $polozka[$kdo]["tata"];
$space = mezera($kdo);
if (strlen($nazev_p)>0) print " $space <a href='index.php?ak=$id_p'>$nazev_p </a> <br>";
if ( (count($strom)>=($kdo+1)) and ($strom[$kdo+1]==$id_p)) vypis($kdo+1,$strom);
// pokud nejsme na konci stromu AND
// zrovna tento prvek je uzel, ktery se tyka prvku, ktery vykreslujeme
// potom posuneme se o prvek dal a vykreslime dalsi cast stromu
// je to rekurze, a tudiz se vratime zpet a dokreslime zbytek
}
}
?>
funkce mezera
neudělá nic jiného, než že vytvoří určitou pevnou mezeru, není třeba dále popisovat (v projektu řeším definováním CSS, např. .uroven1, .uroven2 ....)
funkce posloupnost_k_obsahu($tata)
zjistí, jakou cestou musíme dojít ke kořenu stromu (k hlavní nadkategorii) a poté
při hlavní rekurzivní funkci toto pole procházíme, pole si můžete prohlídnou na pod čaru v
v příkladu.
funkce vypis($kdo,$strom)
hlavní funkce, využívající rekurzi a strom, který jsme vytvořili v předchozí funkci,
doporučuji do výpisů funkce dodat výpis ID, tata, úroveň, abyste zjistili, jak algoritmus funguje. Kdo však zná pojem rekurze, nemělo by to být složité.
Soubor nastaveni.php
Vytvořte soubor nastaveni.php a upravte si proměnné. Pokud pojedete na lokálním PC a budete využívat databázi eshop, pak by tento soubor mohl vypadat následovně
<?
$SQL_Server = "localhost";
$SQL_Uzivatel = "";
$SQL_Heslo = "";
$Databaze = "eshop";
?>
Soubor index.php
<?
require("nastaveni.php");
require("fce/kat.php");
$pripoj = MySQL_Connect($SQL_Server, $SQL_Uzivatel, $SQL_Heslo) or Die(MySQL_Error());
MySQL_Select_Db($Databaze) or Die(MySQL_Error());
$aktualni_kat=$_REQUEST["ak"]*1; //nacteni promenne
$strom = posloupnost_k_obsahu($aktualni_kat); // zjisteni posloupnosti ke korenove kategorii
vypis(0,$strom); //vypsani
print "<hr>A jak vypadá pole strom<br>";
print "<pre>";
print_r($strom);
MySQL_Close($pripoj);
?>
Index.php, není možná ani potřeba komentovat, snad jen pro ty co neznají funkci
print_r - vytiskne pole, proměnnou v nějaké trochu více srozumitelnější podobě. Doporučuji nezkopírovat bezhlavě kód, ale vzít do ruky tužku a papír a snažit se pochopit jak algoritmus funguje. Bude-li mít někdo nějaké doplnění, budu jen rád.