smarty, категории, рекурсия

zeltais

Новичок
smarty, категории, рекурсия

есть табличка id, name, parent_id ( ещё куча полей )
по ней строю меню
соответсвенно пункты, подпункты, подподпункты и т.д., вложенность может быть бесконечная

меню выводится в смарти темплейте
не могу построить логику, получаю бесконечный цикл :(
PHP:
function mainmenu($parent_id=false)
{
	global $smarty,$langId;
	if (empty($parent_id)) { $p=""; } else {  $p="and parent_id='".$parent_id."'"; }
	$query_main_menu="select * from s_module where vieta='main' and lang_id='".$langId."' and status='1' $p order by order_id DESC"; 
	$result_main_menu=mysql_query($query_main_menu);
	while($row_main_menu=mysql_fetch_array($result_main_menu))
		{
			$aMenn[]=$row_main_menu; 
            if($row_main_menu["parent_id"]!="0") { mainmenu($row_main_menu["parent_id"]); }
		}
		$smarty->assign("mainmenu_loop",$aMenn);
}
под конец дня голова пухнет уже, обьясните в чём не прав, что почитать ?
и как бы это отдать в смарти, чтобы в темплейте пропарсить с учётом вложенности ? :(

пы.сы. в поиске был, что такое рекурсия знаю, смарти занимаюсь 2ой день
 

Sokil.Dmytro

Новичок
лучше забить на рекурсию - вызовы функции занимают время, SQL запросы занимают время.

считываешь всю таблицу и дальше работаешь с массивом. массив тоже тормозит но не так! а в смарти ставишь кеш тогда вообще меню не будет прощитываться!

а еще лучше забить на смарти и пользоваться пхп, герерить твое меню кудато в файл и юзать его! пользователи поблагодарят.

у тебя запросы строятся странно

при первом вызове


select * from s_module where vieta='main' and lang_id=$langId and status='1' пусто order by order_id DESC - выбрать всю таблицу

при следующих

select * from s_module where vieta='main' and lang_id=$langId and status='1' and parent_id=$parent_id order by order_id DESC - выбрать част таблици (дак уже ж выбрано)
 

alexhemp

Новичок
zeltais

Бесконечная - это какая?

Что за данные, которым скажем может потребоваться (в реальном приложении) скажем 50 уровней вложенности?

Если количество вставок в базу невелико - используйте Nested Sets вмето списка смежности для хранения дерева.

Для вывода никакой рекурсии не надо, достаточно анализировать текущий "уровень" вложенности, и соотв. этому форматировать вывод. Например можно задать элементу id


например так

<div class=tree id=level1></div>
<div class=tree id=level2></div>
<div class=tree id=levelN></div>

Если число уровней действительно большое (скажем более 5) - то вы уже должны лучше нас знать как сделать, если взялись за такой проект :)
 

zeltais

Новичок
получилось сделать :rolleyes:
PHP:
$aMenn=array();
$smarty->assign("mainmenu_loop",$aMenn);
mainmenu(0);
вот сама функция
PHP:
function mainmenu($parent_id=0,$level=0)
{
	global $smarty,$langId;
	$query_main_menu="select * from s_module where vieta='main' and lang_id='".$langId."' 
and status='1' and shown=1 and parent_id='".$parent_id."' order by order_id DESC"; 
	$result_main_menu=mysql_query($query_main_menu);
	while($row_main_menu=mysql_fetch_array($result_main_menu))
		{
			$aMenn=$row_main_menu;
			$aMenn["level"]=$level;
			$smarty->append("mainmenu_loop",$aMenn);
			$sub_query="select count(*) from s_module where vieta='main' and lang_id='".$langId."' 
and status='1' and shown=1 and parent_id='".$row_main_menu["id"]."' ";
			$sub_result=mysql_fetch_array(mysql_query($sub_query));
			if ($sub_result[0]>0)
				{
					mainmenu($row_main_menu["id"],$level+1);
				}	
		}
}
может не очень правильно и оптимизировано, но как альфа-версия работает :cool:

alexhemp относительно бесконечная.. скрипты реализуют бесконечность, но на самом деле больше 5 уровней врядли будет.. 8)

-~{}~ 28.03.07 17:30:

вот темплейт:
PHP:
{foreach from=$mainmenu_loop item=menu}
&nbsp;
{if $menu.level == 0}
   <b>
{/if}
{section name=sub start=0 loop=$menu.level step=1}
&nbsp; - &nbsp;
{/section}
<a href='?mod={$menu.id}'>{$menu.name}</a><br>
{if $menu.level == 0}
   </b>
{/if}
{/foreach}
 

alexhemp

Новичок
zeltais

Переделай лучше прямо сейчас на вложенные множества.

Потому что количество запросов у тебя при нормальном размере меню будет непотребное.
 
Сверху