Я планирую работать над игрой, у которой есть PHP-сервер для связи с хранилищем данных. Я думал об этом и пришел к выводу, что лучшая парадигма дизайна для нашей игры будет управляться событиями. Я ищу систему достижений (похожую на систему значков этого веб-сайта), и в основном я хотел бы привлечь эти «проверки достижений» к множеству различных событий, которые происходят в игре. то есть:
Когда пользователь выполняет действие X, происходит укус Y и все подключенные функции вызываются для проверки на соответствие требованиям достижения.
При структурировании подобной архитектуры я позволяю легко добавлять новые достижения, так как все, что мне нужно сделать, это добавить функцию проверки на правильный крюк, и все остальное встанет на свои места.
Я не уверен, что это отличное объяснение того, что я намереваюсь сделать, но в любом случае я ищу следующее:
У меня есть несколько идей относительно того, как выполнить 2) и 3), но я надеялся, что кто-то, кто хорошо разбирается в этом вопросе, может пролить свет на лучшие практики.
Заранее спасибо!
Хороший справочный материал о том, как закодировать приложение, управляемое событиями
Вы можете сделать это с помощью «немых» обратных вызовов ( Demo ):
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');
Или внедрение шаблона, часто используемого в приложениях, управляемых событиями: Pattern Observer .
Фрагменты кода, показывающие, как помещать «крючок» в функцию в PHP
Ручная ссылка выше (обратные вызовы могут быть сохранены в переменной) и некоторые примеры кода PHP для шаблона Observer .
Для 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: когда пользователь называет друга, а этот друг подписывает событие, он получает награду за исходный реферист.
Проверьте 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'); } } ?>