インスタンス化したクラスに、クラスメソッド(メンバ関数)を追加できるようにするには、そのクラスにマジックメソッド __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:
- [PHP]クラスメソッドをキャメルケース、スネークケースのどちらでも呼び出せるようにする
- [PHP]htmlspecialchars()を行った上でprintf()する
- [PHP]マジックメソッドを使ったアクセサ(__get, __set)
- [PHP]spl_autoload_register()を使ったクラスファイルの自動読み込みと名前空間(namespace)
- [PHP]多階層ディレクトリ内のファイル一覧を取得する
- [PHP]よくあるエラーメッセージの原因と対処法 2
- [PHP]クラスの基礎 メンバ変数とメンバ関数
- [PHP]PHP7.0での変更点とアップグレード時の対応