※ @mpywさんに指摘いただきましたので、継承させずにインタフェースを使った方法も投稿しました
ArrayAccess,IteratorAggregateインタフェースで配列操作可能なオブジェクトを作成する
Goal
- 配列の添字にアクセスしたときに特定のロジックを実行させたい
-
$array->get(0)
ではなく$array[0]
と書きたい - foreachもサポートしたい
- 具体的な利用例としては、ActiveRecordの遅延評価みたいなことをやりたい
Code
PHPの配列はオブジェクトではないので、配列の要素がアクセスされたことを検知することができない.
配列と同じインタフェースで配列をオブジェクトとして扱えるArrayObjectというライブラリがあるので、これを継承すると、配列操作をフックすることができる.
http://php.net/manual/ja/class.arrayobject.php
<?php
class PersonList extends ArrayObject {
public function offsetGet($index) {
echo "Hello!!";
return parent::offsetGet($index);
}
}
$persons = new PersonList(['Newton', 'Gauss', 'Boltzmann']);
echo $persons[0] . PHP_EOL;
// Hello!!Newton
$persons[0]
のように要素にアクセスすると、offsetGet
メソッドがよばれるのでこのメソッドをオーバーライドして実行したい処理を追加する.
<?php
class PersonList extends ArrayObject {
private function load() {
if ( ! $this->offsetExists(0) ) {
foreach (['Newton', 'Gauss', 'Boltzmann'] as $v) {
$this->append($v);
}
}
}
public function getIterator() {
$this->load();
return parent::getIterator();
}
public function offsetGet($index) {
$this->load();
return parent::offsetGet($index);
}
}
$persons = new PersonList();
// 添字アクセス
echo $persons[0] . PHP_EOL;
foreach ( $persons as $person ) {
// foreachアクセス
echo $person . PHP_EOL;
}
// ■ 添字アクセス結果
// Newton
// ■ foreachアクセス結果
// Newton
// Gauss
// Boltzmann
上記の例では、配列添字アクセスがあったときと、foreachでの配列走査が実行されたタイミングで動的にデータをロードして要素を追加している.
foreachで配列走査が開始されるときにはgetIterator
メソッドがよばれるのでこのメソッドをオーバーライドして実行したい処理を追加する.
offsetExists
メソッドで要素の存在をチェックできるので、要素が0件であればデータをロードする仕組みを作っている.
Environment
$ uname -a
Linux *** 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m
$ /usr/local/php-5.5.4/bin/php -v
PHP 5.5.4 (cli) (built: Mar 11 2014 11:06:57)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
$ /usr/local/php-5.6.0/bin/php -v
PHP 5.6.0 (cli) (built: Aug 29 2014 06:35:44)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies