Создание собственных хуков в CodeIgniter
О том как работать с системными хуками, достаточно подробно написано в документации фреймворка, и сейчас разговор пойдет не о них. Что же такое хуки в принципе и зачем они нужны? Расскажу сразу на примере. Допустим требуется написать фото-галерею, причем некоторый функционал будет существовать как дополнительный, например создание миниатюр. Под дополнительным функционалом я подразумеваю, что приложение должно уметь работать и без него, а при его добавлении, не должно производиться никаких действий с кодом приложения.
Итого, допустим есть некий скрипт который удаляет фото с сервера. В общем виде алгоритм удаления примерно следующий:
- удаляем информацию об изображении из базы данных
- удаляем изображения с диска
- удаляем информацию об изображении отовсюду где она есть
С первыми двумя пунктами вроде все понятно, а вот третий звучит достаточно абстрактно. Гибкое приложение подразумевает модульность. Когда я пишу скрипт удаления изображения, то не хочу думать о том, а какую информацию еще надо удалить и откуда: созданы ли десятки миниатюр в разном размере, или где-то считается количество просмотров картинки... Может быть десяток дополнительных скриптов, которые используют базу картинок, и в каждом из них нужно удалить информацию.
Учитывая, что скрипту удаления заранее не известно, какие модули(модели) в системе хотят получать информацию о событии удаления изображения, очевидно что эту информацию нужно получать из конфигурации приложения.
В СodeIgniter уже существует система событий (хуков), правда разработчики её спрятали как можно дальше. Наверное чтобы никто не писал гибких приложений, а вдруг получиться лучше чем их детище Expression Engine. Я про то, что в официальной документации фреймворка нигде не написано как создавать свои хуки, и наводит на размышление почему класс Hooks не доступен как свойство контроллера, аналогично классам Input, Config, и др.
При вызове события требуется передать какую-то произвольную информацию в произвольном формате, в данном случае информацию о картинке. Передача параметров поддерживается классом хуков, но только из файла конфигурации.
Для решения поставленных задач я предлагаю воспользоваться следующим хелпером:
if (function_exists('hook') === FALSE)
{
function hook($name, $params = array())
{
$EXT = & load_class('Hooks');
if ($params != FALSE)
{
if (isset($EXT->hooks[$name]) === TRUE)
{
if (isset($EXT->hooks[$name][0]) === TRUE)
{
foreach($EXT->hooks[$name] as $k => $v)
{
foreach($params as $key => $value)
{
$EXT->hooks[$name][$k]['params'][$key] = $value;
}
}
}
else
{
foreach($params as $key => $value)
{
$EXT->hooks[$name]['params'][$key] = $value;
}
}
}
}
$EXT->_call_hook($name);
}
}
Теперь после удаления файла изображения с диска и из базы данных я вызываю функцию hook:
hook('on_picture_delete', array('picture_id' => $picture_id));
Настраивать и обрабатывать такое событие точно также как и системные события фреймворка, об этом подробно написано в документации.