Struktura drzewa php mysql
Pokażę jak najlepiej przechowywać strukturę drzewiastą w bazie danych oraz jak później odwoływać się do niej za pomocą php. Załóżmy, że mamy następującą strukturę. Struktura w bazie jest następująca.
Pobieranie dzieci określonego elementu
Teraz zobaczymy jak łatwo dzięki lft i rght pobierzemy potrzebne informacje z bazy danych. Na przykład jeśli chcemy pobrać wszystkie kategorie podrzędne kategorii Tatry wraz z nią samą wystarczy poniższe zapytanie.SELECT * FROM tree WHERE lft >= 2 AND rght <= 13;Jeśli chcemy znaleźć przodków kategorii Makowski.
SELECT * FROM tree WHERE lft < 19 AND rght > 20;W przypadku poszukiwania bezpośredniego rodzica.
SELECT * FROM tree WHERE (lft < 19 AND lft > 1) AND (rght > 20 AND rght < 22);
Przebudowa drzewa
Poniżej przykładowa funkcja przebudowująca strukturę drzewa. Przebudowę rozpoczynamy od wartości licznika $lft oraz elementów głównych.function rebuildTree($parent_id, $lft) { $rght = $lft+1; $result = mysql_query('SELECT id_category FROM categories WHERE id_parent="'.$parent_id.'";'); while ($row = mysql_fetch_array($result)) { $rght = rebuildTree($row['id_category'], $rght); } mysql_query('UPDATE categories SET lft='.$lft.', rght='.$rght.' WHERE id_category="'.$parent_id.'"'); return $rght+1; } rebuildTree(0,0);Algorytm przebudowy można opisać w kilku krokach:
- Zaczynamy od przejścia przez elementy główne (nie mające rodzica) i licznika lft = 0.
- Zwiększamy licznik o 1
- Pobieramy kategorie, dla których id_parent jest równe przekazanemu parent.
- Jeśli znaleziono dzieci wywyłujemy rekurencyjnie rebuildTree z nowymi parametrami (teraz jako parent ustawiamy id_category znalezionego węzła).
- Jeśli nie znaleziono dzieci aktualizujemy bazę odpowiednimi wartościami lft i rght.
- Zwracamy wartość rght powiększoną o 1.
function depths() { $q = 'SELECT node.id_category, (COUNT(parent.id_category) - 1) AS depth'; $q .= ' FROM categories AS node'; $q .= ' CROSS JOIN categories AS parent'; $q .= ' WHERE node.lft BETWEEN parent.lft AND parent.rght'; $q .= ' GROUP BY node.id_category'; $q .= ' ORDER BY node.lft'; $result = mysql_query($q); if(!$result) { die('Invalid query: '. mysql_error()); } $tree = array(); while ($row = mysql_fetch_assoc($result)) { $tree[] = $row; $r = mysql_query('UPDATE categories SET level_depth='.$row['depth'].' WHERE id_category="'.$row['id_category'].'"'); if(!$r) { die('Invalid query: '. mysql_error()); } } return $tree; }