Проблема с деревом
Код:
array_search_key(0, 0);
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.4', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.5', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.6', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.7', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.8', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.9', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($parent, $lvl){
global $menu;
global $lvl;
$lvl++;
foreach($menu as $k=>$v){
if($v['part']==$parent){
echo "<ul>";
echo "";
echo $v['name'];
echo "";
array_search_key($k, $lvl);
$lvl--;
echo "[/list]";
}
}
}
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.4', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.5', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.6', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.7', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.8', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.9', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($parent, $lvl){
global $menu;
global $lvl;
$lvl++;
foreach($menu as $k=>$v){
if($v['part']==$parent){
echo "<ul>";
echo "";
echo $v['name'];
echo "";
array_search_key($k, $lvl);
$lvl--;
echo "[/list]";
}
}
}
де, точняк. ошибка лезет на стадии выполнения;) гм, надо бы разобраться в механизме работы зендомашины или что там в нем. глядишь кодинг эффективнее станет ^^
Самое интересное, что если не делать рекурсии т.е. убрать эту функцию, то все работает по порядку.
1. вызов array_search_key(0,0)
2. в теле функции вызывается foreach цикл и бьется на том, что $menu есть null.
А нужно чтобы было:
1.объявление $menu
2.вызов array_search_key(0,0)
...
и т.п.
Куда ты втыкнешь само тело функции неважно (переходя с perl' а мне эта штука очень понравилась ^^). Суть в том где находится ее вызов:)ъ
Код:
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($parent, $lvl){
global $menu;
global $lvl;
$lvl++;
foreach($menu as $k=>$v){
if($v['part']==$parent){
echo "<ul>";
echo "";
echo $v['name'];
echo "";
array_search_key($k, $lvl);
$lvl--;
echo "[/list]";
}
}
}
array_search_key(0, 0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($parent, $lvl){
global $menu;
global $lvl;
$lvl++;
foreach($menu as $k=>$v){
if($v['part']==$parent){
echo "<ul>";
echo "";
echo $v['name'];
echo "";
array_search_key($k, $lvl);
$lvl--;
echo "[/list]";
}
}
}
array_search_key(0, 0);
А вот результат:
Код:
Раздел 1
Раздел 1.1
Раздел 1.1
А должно быть:
Код:
Раздел 1
Раздел 1.1
Раздел 1.2
Раздел 1.3
Раздел 2
Раздел 1.1
Раздел 1.2
Раздел 1.3
Раздел 2
Теперь, если исключить вызов array_search_key из самой себя, то foreach вернет все нужные значеничения, кроме вложеных конечно. В чем тут соль?
Код:
<?php
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($p,$l)
{
global $menu;
$str = <<<EOF
<ul>
%s
[/list]EOF;
reset($menu);
while (list($k,) = each($menu))
{
if ($menu[$k]['part'] == $p)
{
printf($str,$menu[$k]['name']);
$pos = pos($menu);
array_search_key($k,$l+1);
array_seek($menu,$pos);
}
}
}
function array_seek(&$array, $pos)
{
reset($array);
$cpos = current($array);
while ($cpos !== false && $cpos != $pos)
{
$cpos = next($array);
}
return $cpos;
}
array_search_key(0,0);
?>
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($p,$l)
{
global $menu;
$str = <<<EOF
<ul>
%s
[/list]EOF;
reset($menu);
while (list($k,) = each($menu))
{
if ($menu[$k]['part'] == $p)
{
printf($str,$menu[$k]['name']);
$pos = pos($menu);
array_search_key($k,$l+1);
array_seek($menu,$pos);
}
}
}
function array_seek(&$array, $pos)
{
reset($array);
$cpos = current($array);
while ($cpos !== false && $cpos != $pos)
{
$cpos = next($array);
}
return $cpos;
}
array_search_key(0,0);
?>
Соль в том, что foreach сбрасывает при инициализации внутр. указатель массива, а далее юзает его таким какой он есть, невзирая на то, каким он был на момент последней итерации. А это значит, что с ним рекурсия без особых заморочек не получится.
Вот другой вариант:
Код:
<?php
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($p,$l)
{
global $menu;
$str = <<<EOF
<ul>
%s
[/list]EOF;
foreach (array_keys($menu) as $k)
{
if ($menu[$k]['part'] == $p)
{
printf($str,$menu[$k]['name']);
array_search_key($k,$l+1);
}
}
}
array_search_key(0,0);
?>
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);
function array_search_key($p,$l)
{
global $menu;
$str = <<<EOF
<ul>
%s
[/list]EOF;
foreach (array_keys($menu) as $k)
{
if ($menu[$k]['part'] == $p)
{
printf($str,$menu[$k]['name']);
array_search_key($k,$l+1);
}
}
}
array_search_key(0,0);
?>
Правда сейчас я врдли соображу что экономнее;) Разница тут очевидна, а почему работает без дополнительного контроля над указателем массива счас объясню. На инициализации foreach'а создается анонимный (в perl'е так было, думаю и в php реализация не особо отличается) массив ключей массива $menu, чьим указателем и рулит данный foreach. Когда дело доходит до рекурсии, то все идет по той же схеме, и foreach'и в данном случае юзает не один единственный массив и дружно перемещают указатель то влево, то вправо, а каждый работает со своим собственным экземпляром. Единственный минус который пришел в голову это накладные расходы для хранения этих анонимов, так что тут все зависит от объема этого самого $menu.
фсё, сплу
Все понял, спасибо!