PHP
 Computer >> コンピューター >  >> プログラミング >> PHP

PHPでオブジェクトを反復処理する方法:foreachとIteratorインターフェースの使い方


はじめに

PHP 5以降では、オブジェクトが持つすべての可視項目(プロパティ)を反復処理(イテレーション)することが可能になりました。反復処理には主にforeachループを使う方法と、Iteratorインターフェースを実装する方法の2つがあります。さらにPHPにはIteratorAggregateインターフェースも用意されており、これらを活用することで柔軟な反復処理を実現できます。

foreachループを使った反復処理

最もシンプルな方法は、オブジェクトをそのままforeachループに渡すことです。この場合、そのスコープからアクセス可能なプロパティのみが反復対象となります。クラスの外部から反復した場合はpublicプロパティだけが、クラス内部から反復した場合はprivate・protectedプロパティも含めて取得されます。

サンプルコード

<?php
class myclass{
    private $var;
    protected $var1;
    public $x, $y, $z;
    public function __construct(){
        $this->var="private variable";
        $this->var1=TRUE;
        $this->x=100;
        $this->y=200;
        $this->z=300;
    }
    public function iterate(){
        foreach ($this as $key => $value) {
            print "$key => $value\n";
        }
    }
}
$obj = new myclass();
// クラス外部からの反復:publicプロパティのみ表示される
foreach($obj as $key => $value) {
    print "$key => $value\n";
}
echo "\n";
// クラス内部からの反復:すべてのプロパティが表示される
$obj->iterate();
?>

実行結果

上記のコードを実行すると、次のような結果になります。

x => 100
y => 200
z => 300

var => private variable
var1 => 1
x => 100
y => 200
z => 300

最初のforeachではクラス外からアクセスしているため、publicプロパティであるx・y・zのみが出力されています。一方、クラス内のメソッドiterate()から反復した場合は、privateやprotectedプロパティも含むすべてのプロパティが出力されていることがわかります。

Iteratorインターフェースを使った反復処理

Iteratorインターフェースを実装すると、オブジェクトがどのように反復されるかを細かく制御できます。このインターフェースは以下の抽象メソッドを定義しており、実装クラスでこれらをすべて定義する必要があります。

abstract public current ( void ) : mixed
abstract public key ( void ) : scalar
abstract public next ( void ) : void
abstract public rewind ( void ) : void
abstract public valid ( void ) : bool
  • Iterator::current ― 現在の要素を返す
  • Iterator::key ― 現在の要素のキーを返す
  • Iterator::next ― 次の要素へ移動する
  • Iterator::rewind ― イテレータを先頭の要素に巻き戻す
  • Iterator::valid ― 現在位置が有効かどうかをチェックする

foreachループは内部でこれらのメソッドを自動的に呼び出します。まずrewind()で先頭に戻り、valid()で有効性を確認し、current()とkey()で値を取得し、next()で進む――という流れで反復が行われます。

サンプルコード

次の例は、Iteratorインターフェースを実装してオブジェクトの反復処理を行うものです。各メソッドがいつ呼び出されるかを確認できるよう、echo文を追加しています。

<?php
class myclass implements Iterator{
    private $arr = array('a','b','c');
    public function rewind(){
        echo "rewinding\n";
        reset($this->arr);
    }
    public function current(){
        $var = current($this->arr);
        echo "current: $var\n";
        return $var;
    }
    public function key() {
        $var = key($this->arr);
        echo "key: $var\n";
        return $var;
    }
    public function next() {
        $var = next($this->arr);
        echo "next: $var\n";
        return $var;
    }
    public function valid(){
        $key = key($this->arr);
        $var = ($key !== NULL && $key !== FALSE);
        echo "valid: $var\n";
        return $var;
    }
}
$obj = new myclass();
foreach ($obj as $k => $v) {
    print "$k: $v\n";
}
?>

実行結果

上記のコードを実行すると、次のような結果が出力されます。

rewinding
valid: 1
current: a
key: 0
0: a
next: b
valid: 1
current: b
key: 1
1: b
next: c
valid: 1
current: c
key: 2
2: c
next:
valid:

この出力から、foreachが内部的に「rewind → valid → current → key → next」の順でメソッドを呼び出している様子がよくわかります。最後の要素を処理した後、next()で配列の末尾を超え、valid()がfalseを返した時点で反復処理が終了します。

まとめ

PHPのオブジェクト反復処理には、手軽なforeachループによる方法と、Iteratorインターフェースによるカスタマイズ可能な方法があります。単純にプロパティを列挙したい場合はforeachで十分ですが、独自のコレクションクラスなどを作成する場合はIteratorインターフェース(またはIteratorAggregate)の実装が有効です。用途に応じて使い分けることで、より柔軟で保守性の高いコードを書くことができます。

  1. PHPのmethod_exists()関数とは?メソッドの存在確認方法をわかりやすく解説

    PHPのmethod_exists()関数は、指定したクラスやオブジェクトに特定のメソッドが存在するかどうかをチェックするための組み込み関数です。動的にメソッドを呼び出す前の存在確認など、エラーを防ぎたい場面で非常に役立ちます。基本構文method_exists(object, name_of_method)パラメータobject − チェック対象となるオブジェクトのインスタンス、またはクラス名(文字列)を指定します。name_of_method − 存在を確認したいメソッドの名前を文字列で指定します。戻り値method_name で指定されたメソッドが、対象のオブジェクト(またはクラス)に対

  2. PHPのget_object_vars()関数の使い方を徹底解説

    PHPのget_object_vars()関数は、指定されたオブジェクトが持つプロパティを取得するための関数です。オブジェクト内で定義されているプロパティを、プロパティ名をキーとした連想配列の形式で返します。 構文 get_object_vars(object) パラメータ object − プロパティを取得したいオブジェクトのインスタンスを指定します。 戻り値 get_object_vars()関数は、指定されたオブジェクトの定義済みプロパティを連想配列として返します。まだ値が代入されていないプロパティについては、NULLが返されます。 なお、この関数をクラスの外部から呼び出した場合、取