Итераторы в PHP. Введение
Как известно, важнейшим элементом в языке программирования PHP являются массивы. И это не удивительно, так как практически всегда приходится работать с какими-либо наборами данных. В PHP массивы - ассоциативные, т.е., хранят пары ключ-значение. Ключ массива должен быть либо типа int, либо типа string, а значение может быть любого типа. Массивы в PHP поистине универсальны.
Вот пример операций с массивом:
<?php
$array = [
'a' => 1,
'b' => 2,
'c' => [ 'd', 'e', 'f' ],
];
// добавляем новое значение в массив
$array['x'] = 'Значение 1';
// а здесь индекс формируется автоматически, ( он будет числовой )
$array[] = 'Значение 2';
// в PHP 7 появилась новая особенность
// "распаковка" массива, операция-синоним конструкции list()
[$a, $b, $c, $x, $n ] = $array;
// тоже самое, что и пример выше
list($a, $b, $c, $x, $n) = $array;
?>
Существуют около сотни функции для работы с массивами в PHP. С ними можно ознакомиться на официальном сайте языка.
В добавок ко всем этим функциям, самым главным свойством массивом - является возможность перебора всех элементов, для получения либо ключа, либо значения, либо того и другого сразу. Т.е. итерация по массиву, или процесс прохода по массиву в PHP играет исключительно важное значение. И, несмотря на простоту концепции итерации, за ней кроются мощные возможности, которые можно использовать для перебора любых видов коллекций данных. Фактически процесс итерации обеспечивает нам возможность одинаково работать с любым итерируемым (перебираемым) объектом, а не только с массивом. Т.е. мы можем реализовать следующее:
<?php
class MyClass
{
// общедоступное поле
public $public = "Public Property";
// защищенное поле
protected $protected = "Protected Property";
// закрытое поле
private $private = "Private Property";
}
$myclass = new MyClass();
foreach( $myclass as $prop ) {
echo $prop, PHP_EOL;
}
// Напечатает
// Public Property
?>
Как видно из примера выше, мы можем пройтись по объекту словно по массиву. Но напечатано будет только значение общедоступного свойство, так как защищенные и закрытые поля класса не могут быть прочитаны в цикле. Хотя, практическая польза итерации по свойствам объекта сомнительна, она показывает, что объекты в PHP являются итерируемыми сущностями.
Теперь перейдем непосредственно к примеру. При создании сайтов, а точнее, при написании их программной части, часто используем класс, представляющий хранилище каких-либо настроек, которые можно добавлять и затем получать при необходимости. Такой класс может называться, например, Registry. Вот код:
<?php
// класс хранилища данных
class Registry
{
// массив, в котором хранятся настройки
private $options = [];
// метод для добавления настройки в хранилище
public function set($option, $value)
{
$this -> options[$option] = $value;
}
// метод для получения настройки из хранилища
public function get($option) {
{
return $this -> options[$option];
}
}
?>
Как видно, это простой класс для работы с настройками приложения. Однако, что, если вдруг нам нужно будет пройтись по всем настройкам в хранилище и сделать с ними какую-либо операцию. Но ведь у класса Registry нет открытых свойств, что делать в этом случае? Первое, что приходит в голову это добавить новый открытый метод getOptions() который будет возвращать массив настроек целиком, однако это плохая идея, так как любое случайное изменение в нем может повлиять на все приложение. Поэтому нам нужно другое решение, и это решение - итераторы. В классе Registry мы реализуем интерфейс Iterator. Код:
<?php
// класс хранилища данных, реализующий интерфейс Iterator
class Registry implements Iterator
{
// массив, в котором хранятся настройки
private $options = [];
// возвращает текущий элемент
public function current()
{
return current($this -> options);
}
// возвращает ключ текущего элемента
public function key()
{
return key($this -> options);
}
// передвигаемся вперед на один элемент
public function next()
{
next($this -> options);
}
// возвращает указатель на начало массива
// фактически мы начинаем считать заново с нуля
public function rewind()
{
reset($this -> options);
}
// проверяет, достигли ли мы конца массива
public function valid()
{
return current($this -> options) !== false;
}
// метод для добавления настройки в хранилище
public function set($option, $value)
{
$this -> options[$option] = $value;
return $this;
}
// метод для получения настройки из хранилища
public function get($option)
{
return $this -> options[$option];
}
}
?>
Запуск:
<?php
// создали объект
$reg = new Registry();
// добавили настройки
$reg -> set("DS",DIRECTORY_SEPARATOR)
-> set("APP_HOME", '.')
-> set("AUTO_RELOAD",true)
// и прошлись по настройкам.
// обратите внимание - никаких массивов, только объект $reg
foreach ( $reg as $option => $value ) {
echo $option, " = ", $value, PHP_EOL;
}
?>
Таким образом, мы можем итерировать объекты в PHP, так как будто, они являются массивами. Поэтому итераторы в PHP - это очень мощная технология, и в стандартной библиотеке PHP есть десятки уже готовых итераторов, которые позволяют буквально в пару строк кода выполнить далеко нетривиальные задачи, такие как, например, рекурсивный обход каталога, фильтрация списка на основании некоторого условия или регулярного выражения и т.д.
Поэтому любой уважающий себя PHP программист должен знать и уметь работать с итераторами. Если же Ваши познания в PHP небольшие и Вы хотите качественно и за приемлемый срок выучить этот язык, то в таком случае у меня для Вас есть отличный видеокурс PHP и MySQL с Нуля до Гуру 2.0.
-
- Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.