<rmcreative>

RSS

Итерация по массиву, значения по ссылке

23 сентября 2008

Иногда удобно воспользоваться возможностью PHP5 и использовать передачу по ссылке при переборе элементов массива. Например, для обрезания лишних пробелов у всех элементов:

$arr = array('A', 'B', 'C');
foreach ($arr as &$val) {
  $val = trim($val);
}

//что есть array_walk я знаю

Всё это очень хорошо, но один раз мне пришлось из-за такой возможности очень несладко. Простейший, код, чтобы показать эффект:

$arr = array('A', 'B', 'C');
foreach ($arr as &$val) {}
foreach ($arr as $val) {}
var_dump($arr);
array
  0 => string 'A' (length=1)
  1 => string 'B' (length=1)
  2 => &string 'B' (length=1)

Тогда я вместо var_dump использовал print_r и не увидел &… На самом деле объяснение логичное: после первого цикла $val — ссылка на последний элемент массива. При второй итерации по этой ссылке начнут записываться значения, изменяя массив. Решается проблема так:

$arr = array('A', 'B', 'C');
foreach ($arr as &$val) {}
unset($val);
foreach ($arr as $val) {}
var_dump($arr);

Комментарии RSS

  1. №626
    Ti
    Ti 24 сент. 2008 г., 11:27:47

    да, опасный момент, его нужно знать, я то же как то нарвался

  2. №628
    DeadLy
    DeadLy 24 сент. 2008 г., 13:11:18

    чёт я не совсем понял для чего это нужно

  3. №630
    Sam
    Sam 24 сент. 2008 г., 13:50:27

    Ну, например вот для этого:

    $arr = array(
      array(
       'name' => 'AlEx',
      ),
      array(
       'name' => 'vaSiLy',
      ),
      array(
       'name' => 'JohnnY',
      ),
    );
    foreach ($arr as &$val) {
      //тут делаем ещё много-много всего очень много раз…
      $val['name'] = ucfirst(strtolower(trim($val['name'])));
    }
    unset($val);
  4. №631
    romy4
    romy4 26 сент. 2008 г., 6:56:27

    либо окружить

    if(1)
    {
    foreach($arr as &$val) {...}
    }
     
    // its just for fun :)
  5. №644
    Sam
    Sam 26 сент. 2008 г., 19:23:28

    Про окружить что-то не понял… какой это даст эффект?

  6. №645
    romy4
    romy4 26 сент. 2008 г., 22:10:18

    область действия (жизни) переменной.

    хотя, прошу прощения, ошибся, в PHP переменные созданные в if/do/while/for блоках, живут и после него.

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.