Foreach ассоциативного массива php

Цикл foreach осуществляет последовательный перебор всех элементов массива. Он работает только с массивами и объектами, а в случае его использования с переменными других типов или неинициализированными переменными будет сгенерирована ошибка.

Есть два вида синтаксиса для данного цикла. Первый вид синтаксиса цикла foreach выглядит следующим образом:

Цикл будет перебирать заданный массив — $array (вместо $array подставляется название массива). На каждой итерации значение текущего элемента присваивается переменной $value (можно указать любое другое имя переменной).

Оператор цикла foreach очень удобен, поскольку сам выполняет обход и чтение всех элементов массива, пока не будет достигнут последний. Он позволяет не держать постоянно в памяти тот факт, что индексация массивов начинается с нуля, и никогда не выходит за пределы массива, что делает конструкцию цикла очень удобной и помогает избежать распространенных ошибок.

Посмотрим, как он работает на примере:

Второй вид синтаксиса foreach , выглядит так:

При использовании данной формы синтаксиса на каждой итерации дополнительно присваивается значение текущего ключа переменной $key (можно указать любое другое имя переменной):

Чтобы можно было напрямую изменять элементы массива внутри цикла, нужно использовать ссылку. В этом случае значение будет присвоено по ссылке.

Часто нужно пройти по всем элементам массива PHP и провести какую-нибудь операцию над каждым элементом. Например, вы можете вывести каждое значение в таблицу HTML или задать каждому элементу новое значение.

В данном уроке мы рассмотрим конструкцию foreach при организации цикла по индексированным и ассоциированным массивам.

Цикл по значениям элементов

Самый простой случай использования foreach — это организация цикла по значениям в индексированном массиве. Основной синтаксис :

Например, следующий скрипт проходит по списку режисеров в индексированном массиве и выводит имя каждого:

Выше приведенный код выведет:

Цикл по ключам и значениям

А что насчет ассоциированных массивов? При использовании такого типа массивов часто нужно иметь доступ к ключу каждого элемента, так же как и к его значению. Конструкция foreach имеет способ решить поставленную задачу:

Пример организации цикла по ассоциированному массиву с информацией о кинофильмах, выводит ключ каждого элемента и его значение в HTML списке определений:

Данный скрипт при выполнении выведет:

Изменение значения элемента

А как обстоит дело с изменением значения элемента при проходе цикла? Вы можете попробовать такой код:

Однако, если запустить его на выполнение, то вы обнаружите, что значения в массиве не изменяются. Причина заключается в том, что foreach работает с копией значений массива, а не с оригиналом. Таким образом оригинальный массив остается нетронутым.

Для изменения значений массива вам нужна ссылка на значение. Для этого нужно поставить знак & перед переменной значения в конструкции foreach :

$value становится ссылкой на значение элемента в оригинальном массиве, а значит, вы можете изменять элемент устанавливая новое значение в $value .

— это указатель на оригинальное значение. Она похожа на ярлык в Windows, или на псевдоним в Mac OS.

Например, следующий скрипт проходит циклом каждый элемент (имя режиссера) в массиве $directors , и использует функцию PHP explode() и конструкцию list для перемены мест имени и фамилии:

Отметим, что скрипт вызывает функцию unset() для удаления переменной $director после завершения первого цикла. Это хорошая практика, если вы планируете использовать переменную позже в скрипте в другом контексте.

Если не удалять ссылку, то есть риск при дальнейшем выполнении кода случайной ссылки на последний элемент в массиве ("Lang, Fritz"), если далее использовать переменную $director , что приведет к непредвиденным последствиям!

В данном уроке мы рассмотрели, как использовать конструкцию PHP foreach для организации цикла по элементам массива. Были рассмотрены вопросы:

  • Как организовать цикл по элементам массива
  • Как получить доступ к ключу и значению каждого элемента
  • Как использовать ссылку для изменения значений при проходе цикла

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.elated.com/articles/foreach-loop-through-php-arrays/
Перевел: Сергей Фастунов
Урок создан: 20 Августа 2010
Просмотров: 138259
Правила перепечатки

5 последних уроков рубрики "PHP"

Фильтрация данных с помощью zend-filter

Когда речь идёт о безопасности веб-сайта, то фраза "фильтруйте всё, экранируйте всё" всегда будет актуальна. Сегодня поговорим о фильтрации данных.

Контекстное экранирование с помощью zend-escaper

Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

Подключение Zend модулей к Expressive

Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

Совет: отправка информации в Google Analytics через API

Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

Подборка PHP песочниц

Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

(PHP 4, PHP 5, PHP 7)

Конструкция foreach предоставляет простой способ перебора массивов. Foreach работает только с массивами и объектами и будет генерировать ошибку при попытке использования с переменными других типов или неинициализированными переменными. Существует два вида синтаксиса:

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

Второй цикл дополнительно присвоит ключ текущего элемента переменной $key на каждой итерации.

В PHP 5, когда оператор foreach начинает исполнение, внутренний указатель массива автоматически устанавливается на первый его элемент. Это означает, что нет необходимости вызывать функцию reset() перед использованием цикла foreach.

Поскольку в PHP 5 foreach полагается на внутренний указатель массива, его изменение внутри цикла может привести к непредсказуемому поведению.

В PHP 7 foreach не использует внутренний указатель массива.

Для того, чтобы напрямую изменять элементы массива внутри цикла, переменной $value должен предшествовать знак &. В этом случае значение будет присвоено по ссылке.

Ссылка $value на последний элемент массива останется после окончания цикла foreach. Рекомендуется уничтожать ее с помощью unset() . В противном случае вы можете столкнуться с таким поведением:

= array( 1 , 2 , 3 , 4 );
foreach ( $arr as & $value ) <
$value = $value * 2 ;
>
// $arr = array(2, 4, 6, 8)

// Без unset($value), $value все еще ссылается на последний элемент: $arr[3]

foreach ( $arr as $key => $value ) <
// $arr[3] будет перезаписываться значениями $arr при каждой итерации цикла
echo " < $key >=> < $value >" ;
print_r ( $arr );
>
// . И в конце концов предпоследнее значение определит окончательное содержимое $arr[3]

// вывод:
// 0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
// 1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
// 2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
// 3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
?>

До PHP 5.5.0 указатель на $value возможен, только если на перебираемый массив можно ссылаться (то есть если он является переменной). Следующий код будет работать с PHP 5.5.0:

Оператор foreach не поддерживает возможность подавления сообщений об ошибках с помощью префикса ‘@’.

Еще несколько примеров, демонстрирующие использование оператора:

/* Пример 1: только значение */

$a = array( 1 , 2 , 3 , 17 );

foreach ( $a as $v ) <
echo "Текущее значение переменной $a: $v .
" ;
>

/* Пример 2: значение (для иллюстрации массив выводится в виде значения с ключем) */

$a = array( 1 , 2 , 3 , 17 );

$i = 0 ; /* только для пояснения */

foreach ( $a as $v ) <
echo "$a[ $i ] => $v .
" ;
$i ++;
>

/* Пример 3: ключ и значение */

$a = array(
"one" => 1 ,
"two" => 2 ,
"three" => 3 ,
"seventeen" => 17
);

foreach ( $a as $k => $v ) <
echo "$a[ $k ] => $v .
" ;
>

/* Пример 4: многомерные массивы */
$a = array();
$a [ 0 ][ 0 ] = "a" ;
$a [ 0 ][ 1 ] = "b" ;
$a [ 1 ][ 0 ] = "y" ;
$a [ 1 ][ 1 ] = "z" ;

foreach ( $a as $v1 ) <
foreach ( $v1 as $v2 ) <
echo " $v2
" ;
>
>

/* Пример 5: динамические массивы */

foreach (array( 1 , 2 , 3 , 4 , 5 ) as $v ) <
echo " $v
" ;
>
?>

Распаковка вложенных массивов с помощью list()

(PHP 5 >= 5.5.0, PHP 7)

В PHP 5.5 была добавлена возможность обхода массива массивов с распаковкой вложенного массива в переменные цикла, передав list() в качестве значения.

foreach ( $array as list( $a , $b )) <
// $a содержит первый элемент вложенного массива,
// а $b содержит второй элемент.
echo "A: $a ; B: $b
" ;
>
?>

Результат выполнения данного примера:

Можно передавать меньшее количество элементов в list() , чем находится во вложенном массиве, в этом случае оставшиеся значения массива будут проигнорированы:

foreach ( $array as list( $a )) <
// Обратите внимание на отсутствие $b.
echo " $a
" ;
>
?>

Результат выполнения данного примера:

Если массив содержит недостаточно элементов для заполнения всех переменных из list() , то будет сгенерировано замечание об ошибке:

foreach ( $array as list( $a , $b , $c )) <
echo "A: $a ; B: $b ; C: $c
" ;
>
?>

Результат выполнения данного примера:

Список изменений

ВерсияОписание
7.0.0foreach больше не использует внутренний указатель массива.
5.5.0Поддержка ссылки $value для выражений. Раньше можно было ссылаться только на переменные.
5.5.0Поддержка распаковки вложенных массивов с помощью list() .

User Contributed Notes 21 notes

You can also use the alternative syntax for the foreach cycle:

foreach( $array as $element ):
#do something
endforeach;
?>

Just thought it worth mentioning.

"Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset()."

I cannot stress this point of the documentation enough! Here is a simple example of exactly why this must be done:

= array( "a" => 1 , "b" => 2 , "c" => 3 );
$arr2 = array( "x" => 4 , "y" => 5 , "z" => 6 );

foreach ( $arr1 as $key => & $val ) <>
foreach ( $arr2 as $key => $val ) <>

var_dump ( $arr1 );
var_dump ( $arr2 );
?>

The output is:
array(3) < ["a"]=>int(1) ["b"]=> int(2) ["c"]=> &int(6) >
array(3) < ["x"]=>int(4) ["y"]=> int(5) ["z"]=> int(6) >

Notice how the last index in $arr1 is now the value from the last index in $arr2!

Even though it is not mentioned in this article, you can use "break" control structure to exit from the "foreach" loop.

= [ ‘one’ , ‘two’ , ‘three’ , ‘four’ , ‘five’ ];

foreach( $array as $value ) <
if( $value == ‘three’ ) <
echo "Number three was found!" ;
break;
>
>

foreach and the while/list/each methods are not completely identical, and there are occasions where one way is beneficial over the other.

= array( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 );

foreach( $arr as $key => $value )
<
unset( $arr [ $key + 1 ]);
echo $value . PHP_EOL ;
>
?>
Output:
1 2 3 4 5 6 7 8 9

= array( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 );

while (list( $key , $value ) = each ( $arr ))
<
unset( $arr [ $key + 1 ]);
echo $value . PHP_EOL ;
>
?>
Output:
1 3 5 7 9

[EDIT BY danbrown AT php DOT net: Contains a typofix by (scissor AT phplabs DOT pl) on 30-JAN-2009.]

in foreach if you want to iterate through a specific column in a nested arrays for example:

$arr = array(
[1, 2, 3, 4],
[14, 6, 7, 6],
[10, 2 ,3 , 2],
);

when we want to iterate on the third column we can use:

foreach( $arr as list( , , $a)) <
echo "$a
";
>

WARNING: Looping through "values by reference" for "extra performance" is an old myth. It’s actually WORSE!

function one ( $arr ) <
foreach( $arr as $val ) < // Normal Variable
echo $val ;
>
>

$a = array( ‘a’ , ‘b’ , ‘c’ );
one ( $a );
two ( $a );

?>

Which do you think is faster?

Lots of people think the answer is two() because it uses "reference to value, which it doesn’t have to copy each value when it loops".

Well, that’s totally wrong!

Here’s what actually happens:

— This function takes an array as argument ($arr).
— The array function argument itself isn’t passed by reference, so the function knows it isn’t allowed to modify the original at all.
— Then the foreach loop happens. The array itself wasn’t passed by reference to the function, so PHP knows that it isn’t allowed to modify the outside array, so it therefore makes a copy of the array’s internal iteration offset state (that’s just a simple number which says which item you are currently at during things like foreach()), which costs almost no performance or memory at all since it’s just a small number.
— Next, it uses that copied iteration offset to loop through all key/value pairs of the array (ie 0th key, 1st key, 2nd key, etc. ). And the value at the current offset (a PHP "zval") is assigned to a variable called $val.
— Does $val make a COPY of the value? That’s what MANY people think. But the answer is NO. It DOESN’T. It re-uses the existing value in memory. With zero performance cost. It’s called "copy-on-write" and means that PHP doesn’t make any copies unless you try to MODIFY the value.
— If you try to MODIFY $val, THEN it will allocate a NEW zval in memory and store $val there instead (but it still won’t modify the original array, so you can rest assured).

Alright, so what’s the second version doing? The beloved "iterate values by reference"?

— This function takes an array as argument ($arr).
— The array function argument itself isn’t passed by reference, so the function knows it isn’t allowed to modify the original at all.
— Then the foreach loop happens. The array itself wasn’t passed by reference to the function, so PHP knows that it isn’t allowed to modify the outside array.
— But it also sees that you want to look at all VALUES by reference (&$val), so PHP says "Uh oh, this is dangerous. If we just give them references to the original array’s values, and they assign some new value to their reference, they would destroy the original array which they aren’t allowed to touch!".
— So PHP makes a FULL COPY of the ENTIRE array and ALL VALUES before it starts iterating. YIKES!

Therefore: STOP using the old, mythological "&$val" iteration method! It’s almost always BAD! With worse performance, and risks of bugs and quirks as is demonstrated in the manual.

You can always manually write array assignments explicitly, without references, like this:

= array( 1 , 2 , 3 );
foreach( $a as $key => $val ) <
$a [ $key ] = $val * 10 ;
>
// $a is now [10, 20, 30]

?>

The main lesson is this: DON’T blindly iterate through values by reference! Telling PHP that you want direct references will force PHP to need to copy the WHOLE array to protect its original values! So instead, just loop normally and trust the fact that PHP *is* actually smart enough to never copy your original array’s values! PHP uses "copy-on-write", which means that attempting to assign something new to $val is the ONLY thing that causes a copying, and only of that SINGLE element! 🙂 But you never do that anyway, when iterating without reference. If you ever want to modify something, you use the "$a[$key] = 123;" method of updating the value.

Оцените статью
Много толка
Добавить комментарий