Sziasztok!
Van egy MySQL táblám a következő struktúrával:
Id - Kategória azonosító
Name - Kategória neve
Parent - Melyik kategória alkategóriája(Egy másik kategória id-jét tartalmazza ez a mező)
Egy klasszikus problémát szeretnék megoldani, mégpedig egy fa struktúrát kilistáztatni ebből a táblából. Utána olvastam a dolognak és úgy vettem észre, hogy ez a táblaszerkezet nem igazán előnyös nagy adatmennyiségnél. Nekem csak kevés adattal kell dolgoznom, így ha megoldható a probléma így akkor nem térnék el ettől a struktúrától. Én rekurzívan (ó, jajj) álltam neki a probléma megoldásának úgy, hogy a legfelső szintektől indultam lefele, aztán próbálkoztam már vissza irányba is, de valahogy mindig egy logikai bukfenc lett a kódom vége... Így aki tudna erre nekem szép PHP-s megoldást azt megköszönném nagyon. Közben próbálkozok még majd én is este és linkelek akkor kódot is, hogy kb. merre indultam. Googleztam is sokat, de ilyen adatszerkezettel nem láttam megoldást a problémára, de lehet csak én vagyok vak.
Köszi!
- 5422 megtekintés
Hozzászólások
http://api.drupal.org/api/drupal/modules--taxonomy--taxonomy.module/fun…
Egy megoldás elég hasonló problémára.
- A hozzászóláshoz be kell jelentkezni
Ilyesmi (rekurziv):
function treebranch($allnodes, $node) { // szint gyujtessel
// visszater a gyokertol az adott node-ig tarto faaggal
// elemek sorrendje is ez. gyoker->...->node
if ( -1 == $node['parent'] ) {
$node['treelevel'] = 0;
return array($node['id'] => $node);
}
$parent = $allnodes[$node['parent']];
$roottoparent = treebranch($allnodes, $parent);
$node['treelevel'] = $roottoparent[$parent['id']]['treelevel'] + 1;
return $roottoparent + array($node['id'] => $node);
}
function treefromleaves($allnodes, $needednodes) { // rendezessel
// felepiti a fat a gyokertol az egyes node-okig terjedo agakbol.
// array += array -nal a meglevo elemek a helyukon maradnak, igy a szulok mindig megelozik a
// gyerekeket, ezert bekapcsolhato az opcio, amitol gyorsabb a javascriptes faepito
// (bar utana ugyis rendezzuk, ugyhogy mindegy is lenne...)
$tree = array();
foreach ($needednodes as $needednode)
$tree += treebranch($allnodes, $needednode);
// kulcs osszerendelest meghagyva rendezi szint+sortorder+nev szerint
uasort($tree, create_function(
'$a, $b',
'return strnatcmp(
$a[\'treelevel\'].\'_\'.$a[\'sortorder\'].\'_\'.$a[\'name\'],
$b[\'treelevel\'].\'_\'.$b[\'sortorder\'].\'_\'.$b[\'name\']
);'
)
);
return $tree;
}
- A hozzászóláshoz be kell jelentkezni
Elmeletben az RDBMS-eket nem igazan arra talaltak ki, hogy fa strukturakat taroljanak, de persze a gyakorlatban megis ez szokott tortenni :)
Ket elterjedt megkozelites van: az adjacency list model es a modified preorder tree traversal (MPTT) algoritmus.
Guglizz rajuk.
- A hozzászóláshoz be kell jelentkezni
Nem kell php sem, google closure tables.
- A hozzászóláshoz be kell jelentkezni
plz google: tarolt eljaras, kurzorok (bar rekurziohoz konfigolni kell a mysqld-t)
A teljes strukturat ki akarod rajzolni egyszerre? Vagy csak egy total commander klont akarsz hekkelni?
ja, es mysql verziot kerunk.
Update: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
ha valoban kis mennyisegu elemrol van szo, es nem akarsz a tablastrukturan valtoztatni, akkor az alabbi osztaly(ka) a segitsegedre lehet.
peldanyositod, es az addNode metodussal hozzaadsz elemeket
class Tree {
protected $nodes = array();
protected $edges = array();
public function addNode(array $node) {
$this->edges[$node['id']] = $node['parent'];
$this->nodes[$node['id']] = $node['name'];
}
public function getChildren($id) {
return array_keys($this->edges, $id);
}
public function getParent($id) {
return $this->edges[$id];
}
public function getName($id) {
return $this->nodes[$id];
}
}
- az addNode tombot var, es csak a nevet tarolja el az elen kivul, de lehet durvulni: objektumot var, es az egeszet letarolja nodes-ben (felteve, hogy tobb mezod is van a tablaban, es hasznalni is akarod oket), ez persze a memoria rovasara megy
- ajanlatos az adatbazisbol kapott eredmenyt fetch-eleskor rogton beledobalni, es nem prefetch-elni, szinten memoriatakarekossagi okokbol
- a getName es getParent metodusokba nem irtam ellenorzest, igy konnyen szorhatja a notice-okat! ajanlott kiegesziteni
- a getChildren metodus az array_keys masodik 'search_value' parameterevel trukkozik, igeny szerint harmadik parameternek TRUE-t adva tipusszigoru lesz, bar ha nem flancos az adatbazis-reteg akkor ugyis minden string
- 0, "" es NULL 'id'-ra a getChildren enyhe mellekhatassal dolgozik, de nem veszes (megintcsak ha ertelmes adatok jonnek a tablabol, akkor miert is lenne id=0?)
(szerk.: persze kodot ne kuldjek be tabokkal)
- A hozzászóláshoz be kell jelentkezni
Plastiknak folottem: < code > helyett [code] es jo lesz. Direkt nem irtam rad, meg szerkesztheted.
- A hozzászóláshoz be kell jelentkezni
koszi :)
- A hozzászóláshoz be kell jelentkezni
Köszönöm a sok megoldást! A closure table dolog tűnt elsőre a legszimpatikusabbnak, most annak álltam neki, csak a táblámból kell csináljak egy nézet táblát, ahol az elvárt formában vannak az adatok letárolva. Aztán lehet az lesz a vége, hogy a script lesz módosítva ami dolgozik a kategóriákkal...
- A hozzászóláshoz be kell jelentkezni