[PHP]クラスにメソッドを動的に追加する

Pocket

インスタンス化したクラスに、クラスメソッド(メンバ関数)を追加できるようにするには、そのクラスにマジックメソッド __call() を用意します。
__call() はアクセスが制限されたメソッドや、存在しないメソッドを呼びだそうとした際に実行される関数で、関数名とその引数が渡されます。

PHP 5.3 から無名関数(Closure)が導入され、関数を変数に代入して扱うことができるようになりました。
また、PHP 5.4 では Closure のメソッドに bindTo() が追加され、クラスに関数を追加することが可能となっています。

例としてクラス Sample に hello() という関数を取り付けてみます。

<?php
class Sample
{
	private $functions = array();
	private $hello = 'Hello';
	
	function __call($name, $args){
		$callback = $this->functions[$name];
		return call_user_func_array($callback, $args);
	}
	
	public function bindCallback($name, $callback){
		$this->functions[$name] = $callback->bindTo($this, get_class($this));
	}
}

$sample = new Sample();

$callback = function($str){
	return $this->hello . ', ' . $str;
};

$sample->bindCallback('hello', $callback);

echo $sample->hello("World!");
結果: Hello, World!

$callback に関数 hello() の処理を代入し、bindCallback() で保管しておきます。
$sample->hello() でメソッドを呼ぶと、__call() が実行され、call_user_func_array() によって用意しておいた関数が実行されます。

この方法によって既存のメソッドをオーバーライド(上書き)することはできませんが、書き換えを許可するメソッドを bindCallback() で用意しておけば、プラグインのように後から機能を変更するといった使い方もできると思います。

参考:
http://php.net/manual/ja/closure.bindto.php


Similar Posts:




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です