Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> foreach, Небольшое уточнение 
V
    Опции темы
race1
Дата 28.10.2008, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.6.2004

Репутация: нет
Всего: нет



Код

foreach ($array as $cur_value) {
  ...
}


Как известно, переменная $cur_value не удаляется после выполнения цикла. Это понятно, но почему не работает такой же foreach если вызвать его просто второй раз? Т.е.

Код

$array = ('1', '2', '3');
foreach ($array as $cur_value) {
  print $cur_value;
}
// Выводит 1, 2, 3

foreach ($array as $cur_value) {
  print $cur_value;
}
// Выводит не 1, 2, 3, а, например, 1, 1, 3

foreach ($array as &$cur_value) {
  print $cur_value;
}
// Выводит 1, 2, 3


Просто интересно разобраться, почему так. Разве $cur_value во втором цикле не будет просто перезаписана? И почему правильно работает если использовать ссылку.

Вообще в реальном примере $array это массив массивов массивов, но думаю это не очень важно...

Спасибо.
PM MAIL ICQ   Вверх
HackMan
Дата 28.10.2008, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Юзверь-программист
**


Профиль
Группа: Участник
Сообщений: 391
Регистрация: 18.6.2005
Где: .ua

Репутация: 8
Всего: 9



Цитата(race1 @  28.10.2008,  17:17 Найти цитируемый пост)
$array = ('1', '2', '3');

как-то удивительно, что оно у тебя вообще что-то выводит


--------------------

Завтра - это самый загруженный день недели smile

user posted image

user posted image
PM MAIL ICQ   Вверх
teroni
Дата 28.10.2008, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 15.5.2007
Где: Днепропетровск

Репутация: 8
Всего: 22



Что-то вы намудрили... У меня этот код 123 три раза вывел... Только объявление массива неправильное конечно. У Вас действительно ЭТОТ код печатал во втором цикле 113?
PM MAIL   Вверх
HackMan
Дата 28.10.2008, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Юзверь-программист
**


Профиль
Группа: Участник
Сообщений: 391
Регистрация: 18.6.2005
Где: .ua

Репутация: 8
Всего: 9



этот код кроме Parse error ничего не печатает вовсе


--------------------

Завтра - это самый загруженный день недели smile

user posted image

user posted image
PM MAIL ICQ   Вверх
race1
Дата 28.10.2008, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.6.2004

Репутация: нет
Всего: нет



Насчёт объявления массива это моя ошибка, надо конечно так:
Код

  $array = array('1', '2', '3');


Насчёт реального кода. Да, один foreach для вывода значений массива. В массиве 4 элемента, на выходе было два первых элемента, потом 3-й и 4-й. Сам массив что-то вроде этого:

Код

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Personal Trainers
            [sub_categories] => Array
                (
                    [0] => Array
                        (
                            [id] => 5
                            [name] => Personal Trainers
                        )

                    [1] => Array
                        (
                            [id] => 6
                            [name] => Personal Training Studios
                        )

                )

        )

    [1] => Array
        (
            [id] => 2
            [name] => PRACTITIONERS
            [sub_categories] => Array
                (
                    [0] => Array
                        (
                            [id] => 10
                            [name] => Massage Therapists
                        )

                    [1] => Array
                        (
                            [id] => 11
                            [name] => Massage Therapy Clinic
                        )

                    [2] => Array
                        (
                            [id] => 12
                            [name] => Physiotherapists
                        )

                )

        )
...


Выводил $cur_value['id'] и $cur_value['name']
PM MAIL ICQ   Вверх
HackMan
Дата 28.10.2008, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Юзверь-программист
**


Профиль
Группа: Участник
Сообщений: 391
Регистрация: 18.6.2005
Где: .ua

Репутация: 8
Всего: 9



 smile код в студию, только не выдуманный, а copy-paste из проекта. Чудес не бывает.


--------------------

Завтра - это самый загруженный день недели smile

user posted image

user posted image
PM MAIL ICQ   Вверх
race1
Дата 28.10.2008, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.6.2004

Репутация: нет
Всего: нет



Угу smile Хотя вообще это не так важно, если сразу нет идей почему, лучше просто дальше не копать, я буду делать unset псле каждого foreach.

Есть один файл, который подключает несколько других. Один из этих файлов - левое меню. Там из базы формируется массив который я скопипастил в предыдущем посте, и он выводится через foreach:

Код

    <?php
foreach ($categories as $cur_category) {
    ?>
            <li>
              <a href="#"><?php print htmlspecialchars($cur_category['cat_name']); ?></a>

              <ul>
    <?php
//... что-то не важное
    ?>
              </ul>
            </li>
      <?php
      }
?>


В другом файле мне опять надо вывести эти же категории, опять foreach и теже названия переменных:

Код

<?php
  foreach ($categories as $cur_category) {
?>
    <select id="sub_category_<?php print $cur_category['id']; ?>"
            name="sub_category_<?php print $cur_category['id']; ?>"
            class="hidden">
<?php
    foreach ($cur_category['sub_categories'] as $cur_subcategory) {
?>
      <option value="<?php print $cur_subcategory['id']; ?>"><?php print htmlspecialchars($cur_subcategory['name']); ?></option>
<?php
    }
?>
    </select>
<?php
  }
?>


Вот здесь-то и проявляется косяк, элементы массива выводились два раза первый, потом третий и 4-й.

Это сообщение отредактировал(а) race1 - 28.10.2008, 18:44
PM MAIL ICQ   Вверх
Nigel
Дата 28.10.2008, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


познаю мир
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 20.11.2007

Репутация: 7
Всего: 19



При каждой итерации цикла смещается внутренний указатель массива, однако foreach при запуске делает reset. Вероятно, у вас где-то ошибка в реализации.
По-моему, удобнее в вашем случае использовать array_walk или array_walk_recursive
PM MAIL   Вверх
sTa1kEr
Дата 29.10.2008, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



race1, первые два цикла у вас в примере полностью рабочие, а вот последнем есть распространенная ошибка (думаю из-за этого у вас и проблемы):
Цитата(race1 @  28.10.2008,  18:17 Найти цитируемый пост)
foreach ($array as &$cur_value) {
  print $cur_value;
}

Нужно всегда помнить, что операция по присвоению жесткой ссылки всегда затрагивает обе переменные (они обе помечаются, как "переменная переданая по ссылке") до тех пор пока существует более одной ссылки на значение переменной. А приводит это к тому, что поведение таких переменных несколько отличается, а именно в данном случае это приводит к тому, что последний элемент в массиве будет передаваться по ссылке при копировании массива! Пример:
Код

$array = array(1, 2, 3);
foreach ($array as &$value)
{
   echo $value; // всего-лишь выводим... никакой мистики
}

var_dump($array);
/*
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(3) -- амперсанд тут не с проста!
}
*/

$array2 = $array; // просто копирование
$array2[0] = 10;
$array2[1] = 10;
$array2[2] = 10;

var_dump($array);
/*
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(10) -- значение изменилось, т.к. при копировании массива все его значения были копированы as is
}
*/

// из той-же оперы
function some($arr)
{
    // параметр передан не по ссылке, ожидаем, что все значения были скопированы
    $arr[0] = 100;
    $arr[1] = 100;
    $arr[2] = 100;
}
some($array2);

var_dump($array);
/*
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(100) -- no comments
}
*/

Есть и еще ряд других проблем связанных с амперсандом, по этому крайне желательно избегать их использование. Но если это необходимо, то удалять сразу после использования:
Код

$array = array(1, 2, 3);
foreach ($array as &$value)
{
   $value++;
   unset($value);
}
// такой цикл полностью безопасен
var_dump($array);
/*
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(3)
  [2]=>
  int(4)
}
*/

PM MAIL   Вверх
race1
Дата 30.10.2008, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.6.2004

Репутация: нет
Всего: нет



Спасибо, стало понятнее! smile
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0918 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.