Foreach для object php

foreach

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

foreach (array_expression as $value) statement foreach (array_expression as $key => $value) statement

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

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

Замечание:

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

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

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

$arr = array( 1 , 2 , 3 , 4 );
foreach ( $arr as & $value ) $value = $value * 2 ;
>
// массив $arr сейчас таков: array(2, 4, 6, 8)
unset( $value ); // разорвать ссылку на последний элемент
?>

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

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

Замечание:

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

Вы могли заметить, что следующие конструкции функционально идентичны:

$arr = array( «one» , «two» , «three» );
reset ( $arr );
while (list(, $value ) = each ( $arr )) echo «Значение: $value
\n» ;
>

foreach ( $arr as $value ) echo «Значение: $value
\n» ;
>
?>

Следующие конструкции также функционально идентичны:

$arr = array( «one» , «two» , «three» );
reset ( $arr );
while (list( $key , $value ) = each ( $arr )) echo «Ключ: $key ; Значение: $value
\n» ;
>

foreach ( $arr as $key => $value ) echo «Ключ: $key ; Значение: $value
\n» ;
>
?>

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

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

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

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

foreach ( $a as $v ) echo «\$a[ $i ] => $v .\n» ;
$i ++;
>

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

foreach ( $a as $k => $v ) echo «\$a[ $k ] => $v .\n» ;
>

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

Читайте также:  Xml string parsing in php

foreach ( $a as $v1 ) foreach ( $v1 as $v2 ) echo » $v2 \n» ;
>
>

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

foreach (array( 1 , 2 , 3 , 4 , 5 ) as $v ) echo » $v \n» ;
>
?>

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

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

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

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

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

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

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

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

foreach ( $array as list( $a , $b , $c )) echo «A: $a ; B: $b ; C: $c \n» ;
>
?>

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

Notice: Undefined offset: 2 in example.php on line 7 A: 1; B: 2; C: Notice: Undefined offset: 2 in example.php on line 7 A: 3; B: 4; C:

Источник

Foreach для object php

Beware of how works iterator in PHP if you come from Java!

In Java, iterator works like this :
interface Iterator < O > boolean hasNext ();
O next ();
void remove ();
>
?>
But in php, the interface is this (I kept the generics and type because it’s easier to understand)

interface Iterator < O > boolean valid ();
mixed key ();
O current ();
void next ();
void previous ();
void rewind ();
>
?>

1. valid() is more or less the equivalent of hasNext()
2. next() is not the equivalent of java next(). It returns nothing, while Java next() method return the next object, and move to next object in Collections. PHP’s next() method will simply move forward.

Here is a sample with an array, first in java, then in php :

class ArrayIterator < O >implements Iterator < O > private final O [] array;
private int index = 0 ;

public ArrayIterator ( O [] array) this .array = array;
>

public boolean hasNext () return index < array. length ;
>

public O next () if ( ! hasNext ())
throw new NoSuchElementException ( ‘at end of array’ );
return array[ index ++];
>

public void remove () throw new UnsupportedOperationException ( ‘remove() not supported in array’ );
>
>
?>

And here is the same in php (using the appropriate function) :

/**
* Since the array is not mutable, it should use an internal
* index over the number of elements for the previous/next
* validation.
*/
class ArrayIterator implements Iterator private $array ;
public function __construct ( $array ) if ( ! is_array ( $array ))
throw new IllegalArgumentException ( ‘argument 0 is not an array’ );
$this -> array = array;
$this -> rewind ();
>
public function valid () return current ( $this -> array ) !== false ;
// that’s the bad method (should use arrays_keys, + index)
>
public function key () return key ( $this -> array );
>
public function current () return current ( $this -> array );
>
public function next () if ( $this -> valid ())
throw new NoSuchElementException ( ‘at end of array’ );
next ( $this -> array );
>
public function previous () // fails if current() = first item of array
previous ( $this -> array );
>
public function rewind () reset ( $this -> array );
>
>
?>

Читайте также:  Убрать скобки словарь python

The difference is notable : don’t expect next() to return something like in Java, instead use current(). This also means that you have to prefetch your collection to set the current() object. For instance, if you try to make a Directory iterator (like the one provided by PECL), rewind should invoke next() to set the first element and so on. (and the constructor should call rewind())

class ArrayIterable < O >implements Iterable < O > private final O [] array;

public ArrayIterable ( O [] array) this .array = array;
>

public Iterator < O >iterator () return new ArrayIterator (array);
>
>
?>

When using an Iterable, in Java 1.5, you may do such loops :

for ( String s : new ArrayIterable < String >(new String [] < "a" , "b" >)) .
>
?>
Which is the same as :

Iterator < String >it = new ArrayIterable < String >(new String [] < "a" , "b" >);
while ( it . hasNext ()) String s = it . next ();
.
>
?>
While in PHP it’s not the case :
foreach ( $iterator as $current ) .
>
?>
Is the same as :

for ( $iterator -> rewind (); $iterator -> valid (); $iterator -> next ()) $current = $iterator -> current ();
.
>
?>

(I think we may also use IteratorAggregate to do it like with Iterable).

Take that in mind if you come from Java.

I hope this explanation is not too long.

Источник

Итераторы объектов

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

Пример #1 Итерация простого объекта

class MyClass
public $var1 = ‘value 1’ ;
public $var2 = ‘value 2’ ;
public $var3 = ‘value 3’ ;

protected $protected = ‘protected var’ ;
private $private = ‘private var’ ;

function iterateVisible () echo «MyClass::iterateVisible:\n» ;
foreach( $this as $key => $value ) print » $key => $value \n» ;
>
>
>

foreach( $class as $key => $value ) print » $key => $value \n» ;
>
echo «\n» ;

Читайте также:  Java big range hunting

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

var1 => value 1 var2 => value 2 var3 => value 3 MyClass::iterateVisible: var1 => value 1 var2 => value 2 var3 => value 3 protected => protected var private => private var

Как показывает результат, foreach проитерировал все доступные и принадлежащие объекту видимые свойства.

Кроме того, вы можете развить эту концепцию и реализовать встроенный в PHP 5 интерфейс Iterator . Это позволит самому объекту решать как он будет итерироваться и какие данные будут доступны на каждой итерации.

Пример #2 Объект Iteration, реализующий интерфейс Iterator

class MyIterator implements Iterator
private $var = array();

public function __construct ( $array )
if ( is_array ( $array )) $this -> var = $array ;
>
>

public function rewind ()
echo «перемотка в начало\n» ;
reset ( $this -> var );
>

public function current ()
$var = current ( $this -> var );
echo «текущий: $var \n» ;
return $var ;
>

public function key ()
$var = key ( $this -> var );
echo «ключ: $var \n» ;
return $var ;
>

public function next ()
$var = next ( $this -> var );
echo «следующий: $var \n» ;
return $var ;
>

public function valid ()
$key = key ( $this -> var );
$var = ( $key !== NULL && $key !== FALSE );
echo «верный: $var \n» ;
return $var ;
>

$values = array( 1 , 2 , 3 );
$it = new MyIterator ( $values );

foreach ( $it as $a => $b ) print » $a : $b \n» ;
>
?>

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

перемотка в начало верный: 1 текущий: 1 ключ: 0 0: 1 следующий: 2 верный: 1 текущий: 2 ключ: 1 1: 2 следующий: 3 верный: 1 текущий: 3 ключ: 2 2: 3 следующий: верный:

Интерфейс IteratorAggregate может быть использован как альтернатива реализации всех методов интерфейса Iterator . IteratorAggregate требует чтобы был реализован только один метода — IteratorAggregate::getIterator() , который должен возвращать экземпляр класса, реализующий интерфейс Iterator .

Пример #3 Объект Iteration, реализующий интерфейс IteratorAggregate

class MyCollection implements IteratorAggregate
private $items = array();
private $count = 0 ;

// Требование интерфейса IteratorAggregate
public function getIterator () return new MyIterator ( $this -> items );
>

public function add ( $value ) $this -> items [ $this -> count ++] = $value ;
>
>

$coll = new MyCollection ();
$coll -> add ( ‘value 1’ );
$coll -> add ( ‘value 2’ );
$coll -> add ( ‘value 3’ );

foreach ( $coll as $key => $val ) echo «ключ/значение: [ $key -> $val ]\n\n» ;
>
?>

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

перемотка в начало текущий: value 1 верный: 1 текущий: value 1 ключ: 0 ключ/значение: [0 -> value 1] следующий: value 2 текущий: value 2 верный: 1 текущий: value 2 ключ: 1 ключ/значение: [1 -> value 2] следующий: value 3 текущий: value 3 верный: 1 текущий: value 3 ключ: 2 ключ/значение: [2 -> value 3] следующий: текущий: верный:

Замечание:

Больше примеров итераторов можно найти в расширении SPL.

Замечание:

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

Источник

Оцените статью