Переопределение методов модулей с помощью ...Hook'ов!
26
В LiveStreet 0.4 появилась возможность переопределять не только целиком модули, но и отдельные методы. Это позволить разным плагинам бесконфликтно переопределять разные методы одного модуля.
Принцип действия этого механизма основан на Hook'ах:
Пример:
Список методов для делегирования:
Важное замечание:
Если на module_ModuleName_MethodName_before висит несколько хуков, то сначала они разбиваются на две группы: стандартные и делегирующие. Внутри каждой группы хуки сортируются по приоритету, затем выполняется стандартная группа и только затем делегирующая. Причем в делегирующей группе выполняется только первый хук, остальные отбрасываются для исключения конфликтов.
Принцип действия этого механизма основан на Hook'ах:
- Вызов каждого метода сопровождается выполнением хуков — module_ModuleName_MethodName_before и module_ModuleName_MethodName_after, соответственно ДО и ПОСЛЕ вызова метода модуля. В первом случаи в хук передаются параметры вызова метода, во втором передается результат выполнения метода модуля.
- На module_ModuleName_MethodName_before можно повесить специальный хук — delegate, результат выполнения которого и будет «результатом» выполнения метода модуля
Пример:
<?php
class HookTest extends Hook {
public function RegisterHook() {
$this->AddDelegateHook('module_text_parser_before','testHook',__CLASS__,-3);
}
public function testHook($aVars) {
return 'Topic text > '.$aVars[0];
}
}
?> Здесь происходит переопределение метода Parser модуля Text, в результате к тексту топика будет добавлена строчка 'Topic text > ', при этом исходный метод (Text_Parser()) выполнен не будет.Список методов для делегирования:
Hook_AddDelegateModule($sName,$sCallBack,$iPriority=1)
Hook_AddDelegateFunction($sName,$sCallBack,$iPriority=1)
Hook_AddDelegateHook($sName,$sCallBack,$iPriority=1,$aParams=array()) Использование этих актуально только для хуков методов модулей.Важное замечание:
Если на module_ModuleName_MethodName_before висит несколько хуков, то сначала они разбиваются на две группы: стандартные и делегирующие. Внутри каждой группы хуки сортируются по приоритету, затем выполняется стандартная группа и только затем делегирующая. Причем в делегирующей группе выполняется только первый хук, остальные отбрасываются для исключения конфликтов.
- +10
- 26 марта 2010, 17:46
- ort
«Стандартный» хук и «делегирующий» хук *_before в общем-то абсолютно одинаковы, и отличаются только тем, что «стандартных» может быть сколько угодно, а «делегирующий» — только один, так?
Я бы в таком случае иначе сделал бы. Предлагаю завести некий контейнер статуса выполнения метода, и в нем указывать, надо продолжать выполнение цепочки хуков и самого метода или нет. Плюс — вызов всех параметров по ссылке. Тогда, приведенный выше пример мог бы выглядеть так:
Но если хотим продолжить обработку после нашего хука, то так:
Я бы в таком случае иначе сделал бы. Предлагаю завести некий контейнер статуса выполнения метода, и в нем указывать, надо продолжать выполнение цепочки хуков и самого метода или нет. Плюс — вызов всех параметров по ссылке. Тогда, приведенный выше пример мог бы выглядеть так:
public function testHook(&$aVars) {
Engine::setMethodStatus(HOOK_BREAK);
return 'Topic text > '.$aVars[0];
}Возвращаем обработанный текст и прекращаем его дальнейшую обработку.Но если хотим продолжить обработку после нашего хука, то так:
public function testHook(&$aVars) {
$aVars[0] = 'Topic text > '.$aVars[0];
Engine::setMethodStatus(HOOK_CONTINUE);
return;
}А вот тут мы и текст меняем (меняя содержимое передаваемого аргумента), и позволяем его обрабатывать дальше.
в текущей реализации движок гарантирует две вещи:
1. выполняться все стандартные хуки
2. выполнение хука произойдет до выполнения метода или его делегата, т.к. хук прописан как _before
в твоём подходе ни 1, ни 2 пункт не выполняются, что посеет хаос :)
1. выполняться все стандартные хуки
2. выполнение хука произойдет до выполнения метода или его делегата, т.к. хук прописан как _before
в твоём подходе ни 1, ни 2 пункт не выполняются, что посеет хаос :)
п.2 Я писал только про хуки класса "_before".
п.1 В предлагаемом мной варианте нет деления на «стандартные» и «делегирующие». Любой хук в любое время (в зависимости от логики его работы) может стать, фактически, делегирующим. Когда это может быть полезно: напр., если в хуке проверяется какое-то условие (например, при добавлении топика), и это условие не выполнено и нужно прервать процесс. И в этом случае не играет особой роли, какие хуки выполнились, а какие нет, топик добавлять нельзя.
В изложенном в топике варианте все хуки будут выполняться всегда, даже если этого не нужно.
Если же никакой хук не посчитает нужным прервать выполнение последующих хуков, то оба пункта выполняются без проблем. А хаос — его, при желании, можно в любом месте создать :)
п.1 В предлагаемом мной варианте нет деления на «стандартные» и «делегирующие». Любой хук в любое время (в зависимости от логики его работы) может стать, фактически, делегирующим. Когда это может быть полезно: напр., если в хуке проверяется какое-то условие (например, при добавлении топика), и это условие не выполнено и нужно прервать процесс. И в этом случае не играет особой роли, какие хуки выполнились, а какие нет, топик добавлять нельзя.
В изложенном в топике варианте все хуки будут выполняться всегда, даже если этого не нужно.
Если же никакой хук не посчитает нужным прервать выполнение последующих хуков, то оба пункта выполняются без проблем. А хаос — его, при желании, можно в любом месте создать :)
В предлагаемом мной варианте нет деления на «стандартные» и «делегирующие». Любой хук в любое время (в зависимости от логики его работы) может стать, фактически, делегирующим.результатом этого будет то, что все хуки после делегирующего либо не будут выполнены, либо будут выполнены по факту как _after, хотя они установлены как _bofore.
В изложенном в топике варианте все хуки будут выполняться всегда, даже если этого не нужно.именно, только не все, а стандартные. Один хук не должен влиять на выполнение других(например хуки разных плагинов), кроме случая когда несколько хуков делегирующие. Этот случай аналогичем тому, когда разные плагины делегируют один и тот же модуль.
Да, и передача параметров по ссылке дает неплохие возможности. Напр., может быть плагин, который проверяет орфографию добавляемого топика. А другой плагин — на лету преобразует все ссылки в редирект. Т.е. надо, чтобы исходный сначала был передан 1-му плагину, потом этот измененный текст был передан другому плагину, и уже модифицированный текст отдается парсеру.
комментарий был удален
Интересно как всё это скажется на производительности. Проводились какие-либо замеры?

- MaximusSvargal
- 04 апреля 2010, 01:02
- ↓
комментарий был удален
я, наверное, чего-то не понимаю, но почему
return $this->Topic_GetTopicsByFilter($aFilter,$iPage,$iPerPage);вызывает хук module_Topic_GetTopicsByFilter_before, аreturn $this->GetTopicsByFilter($aFilter,$iPage,$iPerPage); вообще никакого хука не вызывает, как дальше жить?
Комментарии (20)
RSS свернуть / развернуть