Прочитав недавно о нововведениях в PHP 5.3, я заметил несколько интересных особенностей, которые в совокупности могут создать реализацию шаблона проектирования Observer, гораздо более красивую, чем те, что доступны в pear и Symfony, а вся реализация займет всего лишь несколько минут. несколько строк кода.
Новое в 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();
/* Setting up callbacks */
$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 />";
};
/* call */
$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);
}
}
Теперь остаётся только расширить Test из Eventable и наслаждаться результатом: 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();
/* setting up callbacks */
$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 />";
};
/* call */
$test->A("Le Test");
Кстати, в качестве обратных вызовов можно указывать не только анонимные функции, но и нормально объявленные и даже методы класса! $test->onA[] = "some_function";
$test->onA[] = array(&$some_object, "some_method");
Теги: #php5.3 #шаблон наблюдателя #событие #php
-
Как Раскрутить Новичка, Ничего Не Сломав
19 Oct, 24 -
Забавные Нюансы Win10 И Что С Этим Делать
19 Oct, 24 -
Seo-Инструментарий
19 Oct, 24 -
Кто Был Первым.com?
19 Oct, 24 -
Игра «Жизнь» На Логических Элементах.
19 Oct, 24