foreach, isFirst(), isLast(), IteratorAggregate

Splurov

Новичок
foreach, isFirst(), isLast(), IteratorAggregate

Есть желание в php-шаблонах в циклах foreach делать проверки на первый/последний элемент массива. Также хочется, чтобы для этих проверок не нужно было считать количество элементов:
PHP:
$foo = array(
	1=> 'first',
	'second',
	'third',
	'fourth',
	'fifth',
	'sixth',
);

$length = count($foo);
$i = 0;
foreach ($foo as $k => $v) {
	if ($i == 0) {
		echo '(first) ';
	}
	if ($i + 1 == $length) {
		echo '(last) ';
	}
	echo $k . '~' . $v . '<br />';
	$i++;
}
А хочется иметь методы isFirst() и isLast():
PHP:
class Test_Array implements ArrayAccess, IteratorAggregate, Countable {
  
	protected $iterator = null;

	/* вырезал реализации стандартных методов */

	public function getIterator($isNew = true) {
		if ($isNew || is_null($this->iterator)) {
			$this->iterator = new Test_Array_Iterator(clone $this);
		}
		return $this->iterator;
	}

}

class Test_Array_Iterator implements Iterator {

	/* вырезал реализации стандартных методов */

	public function isFirst() {
		return $this->current == 0;
	}
	
	public function isLast() {
		return $this->current + 1 == $this->length;
	}

}

// $foo идентичен массиву из предыдущего примера
$foo = new Test_Array($foo);
foreach ($foo as $k => $v) {
	if ($foo->getIterator(false)->isFirst()) {
		echo '(first) ';
	}
	if ($foo->getIterator(false)->isLast()) {
		echo '(last) ';
	}
	echo $k . '~' . $v . '<br />';
}
Имеет такое право на жизнь? :)
 

Baranov_Dron

Новичок
Re: foreach, isFirst(), isLast(), IteratorAggregate

PHP:
class Test_Array_Iterator implements Iterator {

	/* вырезал реализации стандартных методов */

	public function isFirst() {
		return $this->current == 0;
	}
	
	public function isLast() {
		return $this->current + 1 == $this->length;
	}

}
А так будет не легче?)
PHP:
$array = new ArrayObject(array(1, 2, 3, 4, 5));
$array->setIteratorClass (new Test_Array_Iterator);
Дока по классу ArrayObject http://www.php.net/~helly/php/ext/spl/classArrayObject.html
 

Splurov

Новичок
Baranov_Dron, можно и так, это второстепенно (в моём Test_Array есть другие методы, отсутствующие в ArrayObject).
 

Духовность™

Продвинутый новичок
У меня в шаблонах все массивы - классы типа ArrayAccessImpl.
ArrayAccessImpl - это класс, реализующий интерфейс ArrayAccess и IteratorAggregate. Плюс реализованы методы __set (вызывающий offsetSet()) и __get (вызываюший offsetGet()).

Т.е. выгядит это так:

PHP:
$this->data = new ArrayAccessImpl();
$this->data['element1'] = 'привет';
$this->data->element2 = 'привет 2'; // тоже самое действие, но "как с объектом"
$this->data['element3'] = array(); // element3 на самом деле не массив, а new ArrayAccessImpl()
$this->data['element3']['element31'] = 'подэлемент';
$this->data->element3->element32 = 'теже яйца';
вывод

Код:
ArrayAccessImpl Object
(
    [data:private] => Array
        (
            [element1] => привет
            [element2] => привет 2
            [element3] => ArrayAccessImpl Object
                (
                    [data:private] => Array
                        (
                            [element31] => подэлемент
                            [element32] => теже яйца
                        )
                )
        )
)
-~{}~ 04.03.09 12:27:

Splurov
как определяется? это случайно не счетчик Countable?
 

Splurov

Новичок
Автор оригинала: triumvirat
как определяется? это случайно не счетчик Countable?
PHP:
class Test_Array_Iterator implements Iterator {

	protected $array;
	protected $keys;
	protected $current;
	protected $length;

	public function __construct(Test_Array $array) {
		$this->array = $array;
		$this->keys = $this->array->keys();
		$this->length = $this->array->count();
		$this->rewind();
	}

	public function current() {
		return $this->array->offsetGet($this->keys[$this->current]);
	}

	public function key() {
		return $this->keys[$this->current];
	}

	public function next() {
		$this->current++;
	}

	public function rewind() {
		$this->current = 0;
	}

	public function valid() {
		return $this->current < $this->length;
	}

	public function isFirst() {
		return $this->current == 0;
	}
	
	public function isLast() {
		return $this->current + 1 == $this->length;
	}

}
 

Splurov

Новичок
triumvirat потому что он обязывает использовать ArrayObject, а его я не использую потому что хочется иногда сделать:
PHP:
$foo = new ArrayObject(array(1,2,3));
var_dump($foo->keys());
// или хотя-бы
var_dump(array_keys($foo));
ArrayObject не позволяет работать с объектом как массивом и не позволяет без доп. извращений в потомках получить доступ к исходному массиву.
Или я что то не то хочу/чего то не понимаю?
 

AmdY

Пью пиво
Команда форума
а кто тебе мешает использовать оба?
 
Сверху