オブジェクトをforeachで反復処理

こんにちは、PHP を担当している高杉です。
今回は、PHP5で配列を使用したループを組むときに便利なforeach文の機能について紹介したいと思います。
PHP5以上のforeachであれば、配列だけでなくオブジェクトの反復にも使用することが出来ます。(ただし、PHP4以下では使えません。注意してください)
オブジェクトをforeach文で扱うことができるなら、データを取り出すためにwhile文を使用しなくてもよくなります。foreachを一行書くだけで簡単にイテレーターの処理が可能になり、工数削減や可読性の向上などにつながります。
簡単な使用例
オブジェクトを引数に与えると、foreach(オブジェクト as メンバ変数名 => メンバ変数の値)となり、アクセス権限のあるメンバ変数を全てを取り出します。 以下、サンプルコードです。
class SampleClass {
public $aaa = "aaa";
public $bbb = "bbb";
public $ccc = "ccc";
protected $eee = "eee";
private $fff = "fff";
function anIterator(){
foreach($this as $key => $val){ //自分のインスタンスをforeachに入れて
echo $key . " => " . $val . "<br>"; //出力
}
}
}
//出力用
$sample = new SampleClass();
echo "クラス外からforeachにアクセス<br><br>";
foreach($sample as $key => $val){ //インスタンスをforeachに代入
echo $key . " => " . $val . "<br>"; //出力
}
echo "<br>";
echo "クラス内からforeachにアクセス<br><br>";
$sample->anIterator();
<<出力結果>>
クラス外からforeachにアクセス
aaa => aaa
bbb => bbb
ccc => ccc
クラス内からforeachにアクセス
aaa => aaa
bbb => bbb
ccc => ccc
ddd => ddd
eee => eee
このサンプルコードを実行していただくとわかりますが、foreach文のメンバ変数のアクセスは利用されている状況によって制御されています。
クラス内のアクセスにはメンバ変数を全て表示しますが、クラス外のアクセスでは、protected,privateの変数にはアクセス権がないので表示しません。
Iteratorインターフェイスを実装している例
次に、Iteratorインターフェイスを実装している例を見てみます。 こ場合は、Iteratorインターフェイスの指示に従って取り出すことが出来ます。 例えば、以下は値の最初から2文字だけ切り出す処理を加えたサンプルです。
class SampleIterator implements Iterator {
private $list = array();
public function __construct($list){
$this->list = $list;
}
public function rewind() {
reset($this->list);
}
public function key() {
return key($this->list);
}
public function current() {
return substr(current($this->list), 0, 2); //2文字切り出す
}
public function next() {
return next($this->list);
}
public function valid() {
return current($this->list) !== false;
}
}
$data = array('aaa', 'bbb', 'ccc');
$i_sample = new SampleIterator($data);
foreach($i_sample as $key => $val){
echo $key . " => " . $val . "<br>";
}
<<実行結果>>
0 => aa
1 => bb
2 => cc
このようにforeachでの処理を変化させることが出来ます。
例えば、ログの情報を内部で出力されたままに保持しておき、foreachで取り出す時に必要な形式に変形するするなどの処理に使用できます。
このように、PHP5ではオブジェクトを使用する場合にもforeachは役立ちます。
上手に利用できればアプリケーションの生産性があがることまちがいなしです。




最近のコメント