Jeśli chodzi o przekazanie jakiejś funkcji to:
http://smarty.php.net/manual/en/api.register.function.php-----
Aczkolwiek biorąc ten konkretny przypadek proponuję przeczytaj resztę - trudne to, ale jak będziesz tworzył w oparciu o model MVC (lub inny) to docenisz moje rozwiązanie (choć nie jest optymalne).
-----
A na cholerę przekazywać funkcję do Smarty !? Wykonaj kod który Ci wylistuje co potrzebujesz w TABLICY a tablicy przekaż smarty i foreach'em przejedz. Programuj zgodnie z MVC, nie przekazuj kontroli nad aplikacją do szablonu odpowiadającego za wygląd, niechaj w kodzie PHP będzie sterowanie a tylko w plikach TPL wygląd - staraj się nie mieszać tego.
Skrypt SQL tworzący szkielet rekkurencyjnej bazy kategorii
CREATE TABLE wdb_category (
cat_id int(11) NOT NULL AUTO_INCREMENT,
cat_root_id int(11) NOT NULL DEFAULT 0,
cat_name varchar(100) NOT NULL,
PRIMARY KEY (cat_id)
);
-- przykładowe drzewo kategorii
INSERT INTO wdb_category VALUES (1, 0, '1');
INSERT INTO wdb_category VALUES (2, 0, '2');
INSERT INTO wdb_category VALUES (3, 1, '3');
INSERT INTO wdb_category VALUES (4, 1, '4');
INSERT INTO wdb_category VALUES (5, 4, '5');
INSERT INTO wdb_category VALUES (6, 4, '5');
INSERT INTO wdb_category VALUES (7, 2, '7');
INSERT INTO wdb_category VALUES (8, 7, '8');
INSERT INTO wdb_category VALUES (9, 8, '9');
INSERT INTO wdb_category VALUES (10, 8, '10');
A teraz skrypt PHP tworzący drzewo:
<?php
# funkcja tworzenia drzewa
function find_subcats(&$cat){
if(count($categories)) # jezli pozostaly jakies kategorie foreach($categories as $cat_info) # przelecmy po nich
if($cat_info['cat_root_id'] == $cat['cat_id']){ # jak naleza do korzenia
$cat['subs'][$cat_info['cat_id']] = array( # dodajmy ja ... 'cat_id' => $cat_info['cat_id'],
'cat_name' => $cat_info['cat_name'],
);
find_subcats($cat['subs'][$cat_info['cat_id']]); # ... i dla niej znowu wyszukajmy podaktegorie
}
}
# funkcja wyciągająca kategorie z bazy i wywołująca tworzenie drzewa
function get_cats(){
# wyciagamy wszystkie istniejace kategorie
select
cat_id,
cat_root_id,
cat_name
from
wdb_category
');
# w tablicy je wyciagamy do tablicy $categories
$categories[] = $row;
unset($row); # zwalniamy pamiec
# reszta zajmie sie PHP
# ustawiamy korzen - kategorie nadrzedna dla wszstkich
$cats[0
] = array('cat_id' => 0, 'subs' => array());
#wyszukujemy podkategorie dla drzewa
find_subcats($cats[0]);
#zwracamy drzewo kategorii, poczawszy od korzeni wlasnych; bez 'nad-korzenia' 0
return $cats[0]['subs'];
}
#
# skrypt wlasciwy
#
# pobierzmy kategorie jako tablice
$categories = get_cats();
# i teraz mozna ja traktowac roznorako np.
#lub
#albo do Smarty
$smarty->assign('categories', $categories)
?>
Powiem tylko, że jest to tablica ze zmienno-wymiarowa (głębokość zagnieżdzenia elementów się zmienia) a Smarty operuje liniowo na tablicach i normalnie nie posiada rekurencji, aczkolwiek można to obejść stosując (oczywiście pomijam czysty kod php w {php}...{/php}) rekurencyjne dołączanie tego samego pliku:
<!-- categories.tpl -->
{if count($categories)}
{foreach from=$categories item=category}
<li>{$category.cat_id}: {$category.cat_name}
</li> {if $category.subs}
{include file="categories.tpl" categories=$category.subs}
{/if}
{/foreach}
{/if}
Powyższy skrypt dokładnie dla tych danych (chociaż to mało danych) u mnie na kompie (c2d e6300) zajął
- pamięci = 97592 bajtów
- czasu: 0.001 - 0.0015 s
Edit:
Skrypt nie jest optymalny, tablica kategorii jest kilka razy skanowana w pętli (najoptymalniej by było tylko raz oczywiście). Można by było zrobić jakąś procedurę na serwerze bazodanowym w PL/SQL, aczkolwiek i tak PHP musiałby po tym jeszcze przelecieć bo SQL zwróciłby ewentualnie tylko troszkę przyjaźniej ułożone dane do ułożenia z nich drzewa.