|
[ ducker @ 24.05.2004. 12:40 ] @
| Pozdrav svima!
Imam problem, ne mogu da nadjem pravo (organizaciono) resenje za kategorije. Pokusacu da vam obrazlozim problem sto je moguce detaljnije.
Imam MySQL tabelu:
CREATE TABLE `cats` (
`id` int(10) unsigned NOT NULL auto_increment,
`parent` int(10) unsigned NOT NULL default '0',
`name` varchar(32) NOT NULL default '',
...
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
Ta tabela drzi informacije o kategorijama. Kategorije mogu da imaju ista imena ako se nalaze na razlicitom hijerarhijskom nivou. Zato imam id i parent, a name je samo opis. Znaci, opisi mogu biti isti, ali ne na istom nivou. U adminu proveravam da li postoji red u bazi sa istim parent-om i name-om, ako ima, ne moze da se unese novi. Primer: znaci, putanja do kategorije moze da bude i 'cat24/cat13/cat24/cat45a', a da name='cat24' imaju dva reda u bazi, s tim da ce jednom parent biti 0 (jer je toplevel), a drugom ce parent biti id polja ciji je name 'cat13'.
Jos je vazno da napomenem da ostala polja iz tabele (ona '...') sadrze informacije koje child-ovi nasledjuju od parent-a.
E sad, problem.
Kad hocu da izvucem red iz baze sa tekucom (pod)kategorijom x, a imam putanju npr. cat1/cat2/catx, to radim ovako:
Code:
$x = 'cat1/cat2/catx';
$x1 = explode('/', $x);
$sql_str = "SELECT * FROM cats WHERE name IN ('" . implode ("', '", array_unique ($x1)) . "')";
$sql_return = mysql_query($sql_str);
while ( $out = mysql_fetch_assoc($sql_return) ) $niz[] = $out;
Posle ovoga poredjam $niz po putanji (odnosno po nizu $x1), pa vadim tekuci ( $tekuci = $niz[count($x1)-1] ) koji je ujedno i poslednji, a onda od predzadnjeg trcim redom ka toplevel-u (for ciklusom) i radim update parent-ovim podacima ako tekuci nema naveden taj podatak (to je ono '...' u SQL strukturi).
To radi kako treba (sto kazu, 'drzi vodu'), mada pretpostavljam da i to moze elegantnije da se resi.
Jedino sto mi u ovoj organizaciji nije jasno, to je kako da dobijem isti rezultat na kraju (tj. niz sa podacima o tekucem) ako krecem od:
$x = x; (id kategorije)
a ne sa putanjom ($x = 'c1/c2/...';)
Znaci, pitanje je: kako da nadjem odredjenu (pod)kategoriju (po mogucstvu, sa svim podesenjima koje moze da nasledi od parent-a) ako imam samo njen id? Koliko ja znam, MySQL nema rekurzivne funkcije, ali ne znam kako da ih simuliram u PHPu, a da ne radim na pocetku "SELECT * FROM cats". To mi ipak deluje malo neoptimizovano...
Ima li neko ideju kako ovo resiti, ili bar savet? Nadam se da necu morati zbog ovog problema da radim restruktuiranje baze. A ipak bih zeleo taj deo maksimalno da optimizujem jer se izvrsava u prepend-u svake stranice...
Unapred hvala.
|
[ noviKorisnik @ 25.05.2004. 14:04 ] @
Hm... našao sam ovo. Izgleda mi da ima veze sotim što želiš...
Code: function site_fetch_cat_by_id($id) {
$sql_str = "SELECT * FROM cats";
$sql_return = mysql_query($sql_str);
while ( $outcome = mysql_fetch_assoc($sql_return) ) {
if ( $outcome['id'] == $id ) {
$cats[] = $outcome;
$parent = $outcome['parent'];
} else $db_all[$outcome['id']] = $outcome;
}
if ( !isset($cats) ) {
die('nema...');
}
while ( $parent != 0 ) {
if ( !isset($db_all[$parent]) ) {
die('nema...');
}
$cats[] = $db_all[$parent];
$parent = $db_all[$parent]['parent'];
}
$cats= array_reverse($cats); // evo svih
$cats_cnt = count($cats);
$cat = $cats[$cats_cnt-1]; // evo zadnjeg
// ovde ide to cudo za update-ovanje od parent-a
foreach ( $cats as $c ) {
$cats_names[] = $c['name']; // evo path niza
}
$path = implode('/', $cats_names); // evo path stringa
exit;
}
Jeste da ima samo jedan q, ali mi ne deluje baš optimalno... Možda dobiješ neku ideju. Da nije kojim slučajem ograničena dubina potkategorisanja (recimo na 3 do 4 nivoa)?
[ ducker @ 26.05.2004. 13:48 ] @
Hvala ti, noviKorisnice, to je bas ono o cemu sam i ja razmisljao...
Samo, kao sto si i ti lepo rekao, nekako mi to deluje malo neoptimizovano... Ako u tabeli imam 200+ redova, onda je to jako glupo ako mi trebaju samo dva reda...
Kontam da ni ne moze nikako drugacije.
Na tvoje pitanje: iskreno ne bih nikoga ogranicavao na broj podkategorija, da bih povecao funkcionalnost skripte.
U svakom slucaju, hvala ti, za sada cu koristiti tvoje resenje, dok ne naletim na nesto 'optimizovanije'.
Cheers!
[ -zombie- @ 27.05.2004. 06:45 ] @
možeš da optimizuješ tako što bi za svaku (pod)kategoriju pamtio i na kom je nivou.
ako recimo znaš da je kategorija na 4 nivou, možeš jednim upitom (sa JOINovanjem 4 tabele) da izvučeš sve roditelje te kategorije..
[ ducker @ 01.06.2004. 11:02 ] @
Tomice, ako postavim polje level u bazu, zar nije preveliki problem pomeriti kategoriju na drugo mesto?
Do sada sam morao samo da menjam polje parent, a ovako bih morao da menjam level svih child-ova (i grandchild-ova, itd...) kategorije koju menjam.
Zar ne?
[ -zombie- @ 01.06.2004. 14:12 ] @
naravno, nisam ja tvrdio da je ovo idealno rešenje po svim aspektima..
u stvari, ni ne postoje univerzalno idealna rešenja.. jedno je bolje sa jednog aspekta, drugo sa drugog.. ko ne plati na mostu, platiće.. ne, nije to to.. ;)
pazi, na tebi je da proceniš kako će se ta aplikacija koristiti. meni se čini da akcija "prebaci jednu kategoriju u drugu" nije toliko česta, i da je radi samo admin, i to samo ponekad..
sa druge strane, traženje svih roditelja jedne kategorije je verovatno nešto što će trebati svim posetiocima sajta, i to verovatno često..
tako da..
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|