最近、PHP 5.3の革新を読んで、いくつかの興味深い機能に気づき、それらをリンクして、pearやsymfonyのものよりもはるかに美しいObserverデザインパターンの実装を取得しました。
PHP5.3の新機能
匿名機能。
匿名関数を使用すると、メインコードで関数を宣言せずに、実際に所定の場所にコールバックを作成できます。
__invoke()
新しいマジックメソッドのおかげで、オブジェクトが呼び出されたときに発生するイベントを再定義できます。 つまり、実際には、オブジェクトは関数としてアクセスできます。
クラスイベント
Eventクラス自体から始めましょう。 外部ソースを読み取ることは空にできませんでした。最初に見たイベントを管理する唯一の方法は、connectEventなどの多数のメソッドを実装することでした。
その自然な遅延のため、このルーチンをもう一度やりたくありませんでした。そして、オブジェクトにデータを直接格納し、配列要素のように直接操作できる素晴らしいArrayObjectクラスを思い出しました。 起こったことは次のとおりです。
<?php class Event extends ArrayObject { public function __invoke() { foreach($this as $callback) call_user_func_array($callback, func_get_args()); } }
このクラスのオブジェクトはそれ自体にコールバックを保存し、関数としてオブジェクトにアクセスすると、すべてのコールバックを順番に呼び出します。
例:
<?php $test = new Event(); $test[] = function($msg, $txt) { echo "This is the event! <br />"; }; $test[] = function($msg, $txt) { echo "<b>Message</b>: $msg. <b>Text</b>: $txt <br />"; }; $test[] = function($msg, $txt) { echo "Works great! <br />"; }; $test("Some message", "Some text");
今、それは少し残っているように思えます-これを何らかのクラスに固定すること。 しかし、それはそれほど単純ではありません。
クラスイベント可能
実際、関数としてプロパティにアクセスしようとすると、PHPはプロパティで__invokeを呼び出す代わりに、クラス内でそのような関数を見つけようとしてエラーをスローしようとします。
この例を確認できます。
class Test { public $onA; public function __construct() { $this->onA = new Event(); } public function A($txt) { $this->onA("This is A.", $txt); } } $test = new Test(); $test->onA[] = function($msg, $txt) { echo "This is the event! <br />"; }; $test->A("Le Test");
これは、特にクラスがないため、関数を呼び出すことをクラスに納得させる必要があることを意味します。 私はこれに松葉杖を使わなければならないのではないかと心配しています。誰かがこれよりも美しいソリューションを提供してくれたらとても感謝しています。
<?php class Eventable { public function __call($name, $args) { if( method_exists($this, $name) ) call_user_func_array(array(&$this, $name), $args); else if( isset($this->{$name}) && is_callable($this->{$name}) ) call_user_func_array($this->{$name}, $args); } }
今残っているのは、EventableからTestを拡張し、結果を楽しむことです:
class Test extends Eventable { public $onA; public function __construct() { $this->onA = new Event(); } public function A($txt) { $this->onA("This is A.", $txt); } } $test = new Test(); $test->onA[] = function($msg, $txt) { echo "This is the event! <br />"; }; $test->onA[] = function($msg, $txt) { echo "<b>Message</b>: $msg. <b>Text</b>: $txt <br />"; }; $test->onA[] = function($msg, $txt) { echo "Works great! <br />"; }; $test->A("Le Test");
ところで、コールバックとして、匿名関数だけでなく、通常宣言されたクラスメソッドも指定できます!
$test->onA[] = "some_function"; $test->onA[] = array(&$some_object, "some_method");