Приветствую всех. Я занимаюсь опенкартом относительно недавно, до этого работал с Друпалом. Весь Друпал построен на системе хуков (крючков). С помощью которых один модуль может внести изменения в работу другого. Например один модуль может создать меню, а другой добавить к этому меню новый пункт. Или один модуль может создать тип материала, например Товар с полями Название, Описание, Цена, а другой модуль к этому типу добавить свое поле Производитель. Всего есть десятки хуков с помощью которых можно переопределить почти все - меню, типы материалов, пользователей.. можно добавить свой код например после создания нового материала или при запуске крона итд. В результате получается очень гибкая система, в которой с помощью нескольких строк кода без изменения кода ядра можно сделать что угодно.
В опенкарте все наоборот - никакого механизма что-то изменить нету и даже для казалось бы элементарного действия - создание нового пункта меню из модуля нужно изменять ядро.. Для этого даже придумали костыль - vqmod, который разработчику доставляет кучу проблем, так как файл до изменения его vqmodом уже мог изменить другой модуль или кто-то случайно добавил лишний пробел.. и все, ничего не работает.
Изучив код опенкарта я понял, что весь рендеринг происходит через метод render класса Controller. До рендерига в массив $data собираются данные для каждого шаблона. То есть если перед ренедерингом дать возможность модулям менять массив $data.. то это даст очень мощный инструмент, с помощью которого можно было бы без изменения кода ядра и использования vqmod менять (добавлять, удалять) очень много всего - меню, ссылки, хлебные крошки, информацию о товарах, категориях.. вообще любую переменную шаблона!
Накинул примерную реализацию:
В методе render() класса Controller:
перед
extract($this->data);добавить
$this->hookPreRender();
Добавить метод hookPreRender():
protected function hookPreRender() {
$extensions = $this->model_setting_extension->getExtensions('module');
foreach ($extensions as $extension) {
$action = new Action('module/' . $extension['code']);
$file = $action->getFile();
$class = $action->getClass();
$method = 'preRender';
$action = NULL;
if (file_exists($file)) {
require_once($file);
$controller = new $class($this->registry);
if (is_callable(array($controller, $method))) {
$template = strpos($this->template, $this->config->get('config_template')) !== FALSE ? $this->config->get('config_template') : 'default';
$template = str_replace(array($template . '/template/', '.tpl'), '', $this->template);
call_user_func_array(array($controller, $method), array(&$this->data, $template));
}
}
}
}
Все, всего несколько строк кода..
Теперь в своем модуле можно создать метод контроллера
public function preRender(&$data, $template)
например:
public function preRender(&$data, $template) {
if ($template == 'common/footer' && isset($data['informations'])) {
unset($data['informations'][0]);
}
}Этот код удалит первый элемент массива статей в шаблоне футера.Хочется услышать мнение сообщества насчет подобной инновации. Если вещь стоящая то можно подумать как оптимизировать код и предложить добавить это в оф. релиз движка.