Управляемая событиями архитектура и перехватчики в PHP
Я планирую работать над игрой, у которой есть PHP-сервер для связи с хранилищем данных. Я думал об этом и пришел к выводу, что лучшая парадигма дизайна для нашей игры будет управляться событиями. Я ищу систему достижений (похожую на систему значков этого веб-сайта), и в основном я хотел бы привлечь эти "проверки достижений" к множеству различных событий, которые происходят в игре. то есть:
Когда пользователь выполняет действие X, происходит укус Y, и все присоединенные функции вызываются для проверки на соответствие требованиям достижения.
При структурировании такой архитектуры я буду легко добавлять новые достижения, так как все, что мне нужно сделать, это добавить функцию проверки к правильному крюку и все остальное встанет на свои места.
Я не уверен, что это отличное объяснение того, что я намереваюсь сделать, но в любом случае я ищу следующее:
- Хороший справочный материал о том, как закодировать приложение, управляемое событиями
- фрагмент кода, показывающий, как поставить "крючок" в функции в PHP
- Фрагменты кода, показывающие, как присоединить функцию к "крюку", упомянутому в пункте 2
У меня есть несколько идей относительно того, как выполнить 2) и 3), но я надеялся, что кто-то, кто хорошо разбирается в этом вопросе, может пролить свет на лучшие практики.
Заранее благодарю вас!
Ответы
Ответ 1
Хороший справочный материал о том, как закодировать приложение, управляемое событиями
Вы можете сделать это с помощью "немых" обратных вызовов (Демо):
class Hooks
{
private $hooks;
public function __construct()
{
$this->hooks = array();
}
public function add($name, $callback) {
// callback parameters must be at least syntactically
// correct when added.
if (!is_callable($callback, true))
{
throw new InvalidArgumentException(sprintf('Invalid callback: %s.', print_r($callback, true)));
}
$this->hooks[$name][] = $callback;
}
public function getCallbacks($name)
{
return isset($this->hooks[$name]) ? $this->hooks[$name] : array();
}
public function fire($name)
{
foreach($this->getCallbacks($name) as $callback)
{
// prevent fatal errors, do your own warning or
// exception here as you need it.
if (!is_callable($callback))
continue;
call_user_func($callback);
}
}
}
$hooks = new Hooks;
$hooks->add('event', function() {echo 'morally disputed.';});
$hooks->add('event', function() {echo 'explicitly called.';});
$hooks->fire('event');
Или реализовать шаблон, часто используемый в приложениях, управляемых событиями: Шаблон наблюдателя.
Фрагменты кода, показывающие, как поставить "крючок" в функции в PHP
Ссылка на ссылку выше (обратные вызовы могут быть сохранены в переменной) и некоторые примеры кода PHP для шаблона наблюдателя.
Ответ 2
Для PHP я регулярно интегрировал компонент Symfony Event: http://components.symfony-project.org/event-dispatcher/.
Ниже приведен короткий пример, который вы можете найти в разделе Symfony .
<?php
class Foo
{
protected $dispatcher = null;
// Inject the dispatcher via the constructor
public function __construct(sfEventDispatcher $dispatcher)
{
$this->dispatcher = $dispatcher;
}
public function sendEvent($foo, $bar)
{
// Send an event
$event = new sfEvent($this, 'foo.eventName', array('foo' => $foo, 'bar' => $bar));
$this->dispatcher->notify($event);
}
}
class Bar
{
public function addBarMethodToFoo(sfEvent $event)
{
// respond to event here.
}
}
// Somewhere, wire up the Foo event to the Bar listener
$dispatcher->connect('foo.eventName', array($bar, 'addBarMethodToFoo'));
?>
Это система, которую мы интегрировали в корзину покупок, чтобы создать игровой опыт покупок, подключая действия пользователя к игровым событиям. Когда пользователь выполнил определенные действия, события, инициированные php, вызывают срабатывание вознаграждений.
Пример 1: если пользователь нажал соответствующую кнопку 10 раз, они получили звезду.
Пример 2: когда пользователь ссылается на друга, а этот друг подписывает событие, увольняется, награждая оригинального реферера точками.
Ответ 3
Отметьте CodeIgniter, поскольку он крючки, построенные прямо в.
Просто включите крючки:
$config['enable_hooks'] = TRUE;
И затем определите свой крючок:
$hook['post_controller_constructor'] = array(
'class' => 'Hooks',
'function' => 'session_check',
'filename' => 'hooks.php',
'filepath' => 'hooks',
'params' => array()
);
Затем используйте его в своем классе:
<?php
class Hooks {
var $CI;
function Hooks() {
$this->CI =& get_instance();
}
function session_check() {
if(!$this->CI->session->userdata("logged_in") && $this->CI->uri->uri_string != "/user/login")
redirect('user/login', 'location');
}
}
?>