Забавный случай:
Есть массив $cats - копия таблицы довольно распространенной структуры хранения категорий: (id,parent,name...).
На локальном хосте (PHP 5.2.6) прекрасно работал код:
function getCatsC($pId) {
global $cats;
foreach ($cats as $k=>$v) {
if ($v['parent']==$pId) {
}
}
}
function getCatsP($rootId) {
global $cats;
foreach ($cats as $k=>$v) {
if ($v['parent']==$rootId) {
getCatsC($k);
}
}
}
getCatsP(0);
т.е. тупой перебор родителей-детей с линковкой их в нужную HTML структуру.
Заливаю на хостинг (PHP 5.1.6) - линкует только первого родителя и его детей.
Благо проблему нашел быстро, но ее смысл меня несколько обескуражил.
Дело в том, что оказалось, что в foreach циклах внутренний указаталь на локалке был локальным, а на хосте стал глобальным! т.е. при вызове линковки детей сбивался указатель для родительского цикла!
Для тех, кто подумал, что я думаю что они подумали - ссылка:
http://www.php.su/learnphp/cs/?cycles#foreach с таким вот текстом:
.
Т.е. мне пришлось просто переписать код так:
$cats2=$cats;
function getCatsC($pId) {
global $cats2;
foreach ($cats2 as $k=>$v) {
if ($v['parent']==$pId) {
}
}
}
function getCatsP($rootId) {
global $cats;
foreach ($cats as $k=>$v) {
if ($v['parent']==$rootId) {
getCatsC($k);
}
}
}
getCatsP(0);
ну и сей казус объяснить кроме как тем, что это очередной ляп в
php-реализациях - я ничем не могу.
Помогите!!! Сон потерял!!! :D
Спустя 9 минут, 5 секунд (23.09.2011 - 11:49) Sanchopansa написал(а):
Может проще передать этот массив как параметр функции и не париться?
типа:
function getCatsC($pId, $cats) {
foreach ($cats as $k=>$v) {
if ($v['parent']==$pId) {
}
}
}
function getCatsP($rootId, $cats) {
foreach ($cats as $k=>$v) {
if ($v['parent']==$rootId) {
getCatsC($k, $cats);
}
}
}
getCatsP(0, $cats);
Спустя 1 минута, 55 секунд (23.09.2011 - 11:51) redreem написал(а):
я и не парюсь
![smile.gif](http://phpforum.ru/html/emoticons/smile.gif)
проблема решена уже как я писал. смысл на каждом родителе передавать лишний параметр? дело в другом - почему вообще такая проблема возникла???
Спустя 1 час, 46 минут, 28 секунд (23.09.2011 - 13:37) linker написал(а):
Проблема не в PHP, проблема в изначально неверном алгоритме.
Спустя 12 минут, 25 секунд (23.09.2011 - 13:50) redreem написал(а):
я не прошу обсуждать алгоритм. давайте не будем отвечать на те вопросы, на которые мы сами хотим ответить. тема во флейме, поэтому либо по существу ситуации либо вообще лучше не писать.
Спустя 2 минуты, 52 секунды (23.09.2011 - 13:53) redreem написал(а):
linker, алгоритм нормальный. я же не показал всего кода, там на 100 строк в каждой функции еще понаписано. раз такой способ я применил - значит мне так нужно.
Спустя 1 час, 8 минут, 25 секунд (23.09.2011 - 15:01) redreem написал(а):
для проверки:
getCats();
$GLOBALS['console']->addData($cats);
function getCatsC($pId) {
global $cats;
foreach ($cats as $k=>$v) {
if ($v['parent']==$pId) {
$GLOBALS['console']->addData($v);
}
}
}
function getCatsP($rootId) {
global $cats;
foreach ($cats as $k=>$v) {
if ($v['parent']==$rootId) {
$GLOBALS['console']->addData($v);
getCatsC($k);
}
}
}
getCatsP(0);
Спустя 2 минуты, 3 секунды (23.09.2011 - 15:03) redreem написал(а):
и еще раз проблема: в foreach указатель должен быть локальным для каждого раза! а он на хостинге оказывается глобальным!
Спустя 3 часа, 26 минут, 48 секунд (23.09.2011 - 18:30) redreem написал(а):
Спустя 5 часов, 6 минут, 47 секунд (23.09.2011 - 23:37) kirik написал(а):
Вообще довольно странно, ибо:
Цитата (http://php.net/manual/en/control-structures.foreach.php) |
Note:
When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop. |
Но можно попробовать перед самим циклом вставить reset().
Спустя 3 минуты, 58 секунд (23.09.2011 - 23:41) redreem написал(а):
да, но как быть вот с этим утверждением:
http://www.php.su/learnphp/cs/?cycles#foreach с таким вот текстом:
Цитата |
Внимание: Цикл foreach оперирует не исходным массивом, а его копией. |
Спустя 12 минут, 28 секунд (23.09.2011 - 23:53) neadekvat написал(а):
Цитата (redreem @ 23.09.2011 - 12:40) |
ну и сей казус объяснить кроме как тем, что это очередной ляп в php-реализациях - я ничем не могу. |
Ой, и правда.
А давайте на четвертой версии php попробуем?
Мало ли чего там в php 5.1 и 5.2 было? Там на каждую новую версию (5.x.y - я про y) столько багфиксов выдают, что порой волосы шевеляться. А ты от старых версий что-то хочешь.
В php 5.3 все ок.
Спустя 3 минуты, 59 секунд (23.09.2011 - 23:57) kirik написал(а):
redreem
Вот за это я и не люблю всякие там php.su.
Цитата (http://www.php.su/learnphp/cs/?cycles#foreach) |
Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it. |
По поводу утверждения - он работает с самим массивом (оригинальным), пока ты не внёс изменения в массив (т.е. php создаёт копию только в крайнем случае).
Спустя 24 минуты, 6 секунд (24.09.2011 - 00:21) redreem написал(а):
хорошо, тогда последний вопрос: почему различие в работе на локальном хосте и на внешнем???
Спустя 56 минут, 49 секунд (24.09.2011 - 01:18) kirik написал(а):
redreemНе могу знать.. может у тебя локально денвер стоит, а он, как известно, по-своему работает
Спустя 9 часов, 12 минут, 17 секунд (24.09.2011 - 10:30) redreem написал(а):