Довольно неожиданно пришла идея довести начатый шаблонизатор до юзабельного вида, дописал хелперы, встроил кеширование, решил прицепить хелпер для формы. И здесь мне стало нехватать ООП стиля. Накидав кой-чего понял что вначале нужно написать цикл статей о SPL (Стандартной PHP библиотеке). Эта штука очень полезна при ООП стиле кодирования, а особо нормальных статей об SPL на русском я не обнаружил.
Начнёмс.
ArrayObject — предназначен для того, чтобы объект вёл себя как массив, даёт доступ к данным через квадратные скобки и позволяет делать foreach
ArrayObject implements IteratorAggregate , Traversable , ArrayAccess , Countable {
/* Methods */
ArrayObject::__construct ( mixed $input )
void ArrayObject::append ( mixed $newval )
int ArrayObject::count ( void )
ArrayIterator ArrayObject::getIterator ( void )
bool ArrayObject::offsetExists ( mixed $index )
mixed ArrayObject::offsetGet ( mixed $index )
void ArrayObject::offsetSet ( mixed $index , mixed $newval )
void ArrayObject::offsetUnset ( mixed $index )
}
Данный класс имплементирует интерфейсы IteratorAggregate , Traversable , ArrayAccess , Countable
IteratorAggregate , Traversable — отвечают за гуляние по объекту, соответственно нужно реализовать метод getIterator. Эти вещи будем разбирать в другой раз.
Countable — нужно реализовать интерфейс для получения размера count.
ArrayAccess — это квадратные скобочки — проверка существования offsetExists, получение значения — offsetGet, присвоение значения — offsetSet, уничтожение элемента — offsetUnset и добавление элемента — append.
Со скучной теорией покончено, сейчас практика
class Amdy_Array extends ArrayObject {
protected $array;
public function __construct($array) {
$this->array = $array;
}
public function append($value) {
$this->array[] = $value;
}
function offsetSet($key, $value) {
if ($key) {
$this->array[$key] = $value;
} else {
$this->array[] = $value;
}
}
function offsetGet($key) {
if ( array_key_exists($key, $this->array) ) {
return $this->array[$key];
}
}
function offsetUnset($key) {
if ( array_key_exists($key, $this->array) ) {
unset($this->array[$key]);
}
}
function offsetExists($offset) {
return array_key_exists($offset, $this->array);
}
public function dump() {
var_dump($this->array);
}
}
Так мы побыстрому создали свой обработчик, унаследовав класс из SPL. Что же там происходит.
В конструктор передаётся сам массив, его можно передать и позже, но не важно. Данный массив мы загоняем во внутреннюю переменную $this->array, дальше, мы описываем, как должны обрабатываться запросы к объекту как к массиву. Т.е. все запросы будут реально относиться в переменно $this->array. Можно и вовсе не заводить эту переменную, а работать с атрибутами класса, если в коде заменить $this->array, на get_class_vars($this), $this->{$k} и т.д.
Простой пример использования.
$array = new Amdy_Array(
array(
'test',
'test1' => array(0,1,2,3),
2,
'test4' => 'test2 value'
)
);
$array[] = 'test2222';
echo $array[0] . '<hr/>';
echo $array['test4'] . '<hr/>';
$array->dump();
PHP не стоит на месте, потому, кое-что уже изменилось, постоянно добавляются новые классы, методы и интерфейсы, чтобы не изобретать свои велосипеды.
Поделиться в соц. сетях
Похожие посты:
Спасибо за информацию. Буду знать.
Прикольно!
Но массивы не могут быть многомерными, ну в смысле многомерными они быть могут, но выглядит не совсем хорошо!
$array[1] = new ArrayObject;
$array[1][1] = ‘Ячейка 1:1′;
В таком случае спасает рекурсия в конструкторе, в конечном итоге будет ещё и обёртка для строк и итератор, статью о котором я всё никак не могу дописать. Всё это очень пригодится для обработки входных данных из $_REQUEST
class MyArrayObject extends ArrayObject
{
protected $array = array();
public function __construct($array = array())
{
foreach ((array) $array as $key => $value)
{
if (is_array($value))
{
$this->array[$key] = new self($value);
}
else
{
$this->array[$key] = $value;
}
}
}
public function offsetGet($key)
{
if (array_key_exists($key, $this->array))
{
return $this->array[$key];
}
}
public function offsetSet($key, $value)
{
if ($key)
{
$this->array[$key] = $value;
}
else
{
$this->array[] = $value;
}
}
public function offsetUnset($key)
{
if (array_key_exists($key, $this->array))
{
unset($this->array[$key]);
}
}
public function offsetExists($key)
{
return array_key_exists($key, $this->array);
}
public function append($value)
{
$this->array[] = $value;
}
public function count()
{
return count($this->array);
}
public function getIterator()
{
return new ArrayIterator($this->array);
}
public function __toString()
{
return ‘Array’;
}
}
Согласен, рекурсивный конструктор выглядит лучше, а вот об интерфейсе итератора статья уже в разработке, правда, с декабря
.
В __toString(), наверное, лучше бросать exception или уже делать implode
Не могу понять в чем различие между
class Amdy_Array Implements ArrayAccess
и
class Amdy_Array extends ArrayObject
Включил мозг и разобрался
Опечатки: особо ноРмальных статей об SPL на русском я не обноружиЛ
Жду новых статей об SPL.
спасибо огромное, поправил эти и ещё парочку, как же тяжело было без проверки орфографии в opera, да ещё с моей грамотностью
можешь назвать пару примеров, когда пригодится обращаться к объекту как к массиву?
Когда, например, получаешь строку из БД как объект, и обращаешься к нему, как к массиву.
100500 примеров из JS
хм, случайно наткнулся на твой блог (:
а почему не так, раз уж ты ничего в поведении не меняешь?
class Amdy_Array extends ArrayObject {
public function __construct( … ) {
// получаем откуда-то массив
parent::__construct( $array );
}
…
}