[PHP][CodeIgniter] Jak utworzyć wielopoziomowe kategorie?
Ostatnio, pobawiłem się trochę frameworkiem PHP o nazwie CodeIgniter (moim zdaniem jeden z fajniejszych frameworków PHP) i w ramach sprawdzenia go stworzyłem prosty CMS.
Jednym z problemów jakie trzeba było rozwiązać był problem utworzenia wielopoziomowego drzewa kategorii newsów, aby wstawić go do znacznika <select> w kodzie formularza. Jestem pewien, że wiele osób miało/ma z tym problem.
Rekurencja - co to jest?
By wykonać tego typu zadanie należy zaznajomić się z pojęciem rekurencji.
Rekurencja - (w programowaniu) odwoływanie się funkcji do samej siebie
Definicja jest prosta w zrozumieniu, a jak to wygląda w przypadku funkcji w PHP (w tym przypadku, frameworku PHP - CodeIgniter)?
Przygotowanie bazy danych
Na początku należy utworzyć w bazie danych tabelę z trzema kolumnami:
- kategoria_id
- rodzic_id
- kategoria_nazwa
Generowanie wielopoziomowych kategorii w CodeIgniter
W oparciu o tak podany schemat bazodanowy, utworzymy odpowiednie funkcje, które należy wstawić do modelu, który ma obsługiwać system newsów.
Należy pamiętać o tym, że programując cokolwiek z użyciem frameworków PHP, korzystamy ze wzorca MVC (odpowiednio dostosowanego do PHP) i aplikację mamy podzieloną na 3 części składowe:
- Model (M) - w nim znajdują się metody/funkcje odpowiedzialne za przetwarzanie danych z bazy danych oraz danych wprowadzanych przez użytkownika
- Widok (V) - w nim znajduje się szablon strony na której dane (odpowiednio przygotowane przez model, a następnie przekierowane przez kontroler) będą wyświetlane
- Kontroler (C) - w nim znajdują się metody/funkcje pozwalające na odpowiednie przygotowanie danych przed wysłaniem do modelu czy widoku
Kod odpowiedzialny za tworzenie wielopoziomowych kategorii wygląda następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | /* * Funkcja generująca widok listy rozwijanej <select> */ function getCategories() { $list = ''; $q = 'SELECT * FROM kategorie WHERE rodzic_id IS NULL'; $wynik = $this->db->query($q); $rodzic = $wynik->result_array(); $mainlist = '<select name="kategoria">'; foreach($rodzic as $p) $mainlist .= $this->categoryTree($list, $p, $append = 0); $mainlist .= '</select>'; return $mainlist; } /* * Funkcja generująca kolejne gałęzie drzewa kategorii * na liście rozwijanej <select> * dla widoku pisania newsa */ function categoryTree($list, $rodzic, $append) { if($this->hasChild($rodzic['kategoria_id'])) { $append++; $list = '<optgroup label="'.$this->addWhitespace($append).$rodzic['kategoria_nazwa'].'">'; $q = 'SELECT * FROM kategorie WHERE rodzic_id = "'.$rodzic['kategoria_id'].'"'; $wynik = $this->db->query($q); $dziecko = $wynik->result_array(); foreach($dziecko as $rodzic) $list .= $this->categoryTree($list, $rodzic, $append); $list .= '</optgroup>'; } else { $list = '<option value="'.$rodzic['kategoria_id'].'">'.$this->addWhitespace($append,1).$rodzic['kategoria_nazwa'].'</option>'; } return $list; } /* * Funkcja dodająca twarde spacje do ciągu * w celu sformatowania układu */ protected function addWhitespace($n,$dodaj=0) { $w = ' '; $space = ''; for($i=0;$i<$n;$i++) $space .= $w; if($dodaj==1) return $space.' '; else return $space; } |
Uważam że kod jest dość jasno opisany i nie potrzebuje większego tłumaczenia. Jednak muszę wspomnieć o tym, że przed wykonaniem powyższego kodu należy pamiętać o zaladowaniu biblioteki CodeIgnitera dzięki której będzie możliwe korzystanie z metod bazodanowych, np.: $this->db->query.
Bardzo możliwe, że znajdzie się ktoś kto powyższy kod mógłby jeszcze bardziej zoptymalizować, ale na potrzeby tego tutoriala jest on całkowicie wystarczający i jasny (mam nadzieję).