SPL расшифровывается как Standard PHP Library. Это набор классов и интерфейсов для решения стандартных задач на PHP. В основном она состоит из различного рода итераторов. Библиотека доступна по умолчанию, начиная с PHP 5.
Приведу несколько примеров, начнем с класса Traversable. Этот интерфейс показывает что к данному объекту применим foreach. Этот базовый интерфейс нельзя реализовать напрямую, а через интерфейсы IteratorAggregate или Iterator.
Iterator
Iterator - класс для перебора внутренних параметров. Объявление итератора:
Iterator extends Traversable {
/* Методы */
abstract public mixed current ( void ) // Возвращает объект на который указывает итератор
abstract public scalar key ( void ) // Возвращает текущую позицию итератора
abstract public void next ( void ) // Переход к следующему элементу
abstract public void rewind ( void ) // Возврат к началу
abstract public boolean valid ( void ) // Проверка на доступность объекта, на который указывает итератор
}
Каждый из этих методов должен быть реализовать в классе - потомке, реализуя функционал итератора. Приведу пример:
class myIterator implements Iterator {
private $position = 0; // Текущая позиция
// Перечень элементов, именно по нему будет бегать итератор
private $array = array(
"firstelement",
"secondelement",
"lastelement",
);
// Конструктор, кэп
public function __construct() {
$this->position = 0;
}
function rewind() {
var_dump(__METHOD__);
$this->position = 0;
}
function current() {
var_dump(__METHOD__);
return $this->array[$this->position];
}
function key() {
var_dump(__METHOD__);
return $this->position;
}
function next() {
var_dump(__METHOD__);
++$this->position;
}
function valid() {
var_dump(__METHOD__);
return isset($this->array[$this->position]);
}
}
$it = new myIterator;
foreach($it as $key => $value) {
var_dump($key, $value);
echo "\n";
}
Как видно из кода, сначала объявляется класс, в которой существует массив, по которому и будет бегать наш итератор. Потом мы пробегаемся по каждому элементу при помощи foreach. В результате выполнения этого кода, будет выведено следующее:
string(18) "myIterator::rewind"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
int(0)
string(12) "firstelement"
string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
int(1)
string(13) "secondelement"
string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
int(2)
string(11) "lastelement"
string(16) "myIterator::next"
string(17) "myIterator::valid"
По этому коду можно проследить порядок работы итератора.
ArrayAccess
Этот класс предоставляет возможность обращаться к объекту как к массиву, что в некоторых случаях может сильно облегчить код, а также ввести в когнитивный диссонанс человека, не знакомого с этим интерфейсом.
ArrayAccess {
/* Методы */
abstract public boolean offsetExists ( mixed $offset ) // Существует ли объект с данным ключом.
abstract public mixed offsetGet ( mixed $offset ) // Получение объекта
abstract public void offsetSet ( mixed $offset , mixed $value ) // Присвоение
abstract public void offsetUnset ( mixed $offset ) // Удаление
}
Вы сами можете определить как именно будет работать ваш объект, что позволяет достичь большой гибкости.
Пример:
class obj implements arrayaccess {
private $container = array();
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
$obj = new obj;
var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
В результате получили:
bool(true)
int(2)
bool(false)
string(7) "A value"
obj Object
(
[container:obj:private] => Array
(
[one] => 1
[three] => 3
[two] => A value
[0] => Append 1
[1] => Append 2
[2] => Append 3
)
)
При правильном использовании поможет вам сделать ваш код лаконичнее и красивее.