8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPで配列の要素アクセスをフックする

Last updated at Posted at 2015-03-07

@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
8
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?