контроллер — это специализированная сущность для управления другими сущностями.
Часто используют функциональные контроллеры, основанные на найменге (naming) примеры всем широко известны, например плагины смарти:
smarty_type_name() как видите из документации, плагин становится доступным если объявлены соответствующие функции.
в целом там простой контроллер который ищет функцию по простым правилам, основанных на именовании.
часто такие вызываемые сущности хочется проинкапсулировать или иначе собрать и закрыть во что-либо, в результате появляются файлы с типично функциональным подходом:
mylib.php:
конечно, это не гарантирует целостности, засоряет глобальное пространство имен и проч.
Удобно такие вещи проинкапсулировать в класс:
далее не сложно понять как нужно сделать контролер, основанный на method_exists, которому первым аргументом вполне можно давать имя класса-контейнера. Как правило, на этом фантазия останавливается, но из объектной парадигмы можно извлечь еще много различных выгод:
перейду к рассмотрению сразу же конкретной задачи, чтоб на примере было проще понять идею.
хотим реализовать простой контролер выбора отображаемой страницы модуля.
для начала покажу самый дурной вариант того как это делают:
хуже только варианты с if-elseif-else, чтоб такого не было пишут контроллер, например, как в смарти, основанный на найменге:
но я опишу немножко другой подход, более формальный:
тут код в цвете: dumpz.org/2513
а тут просто код, чтоб не бегать:
контроллером является функция "buildPage"
таким образом если вызвать скрипт
example.com/?action=hello
то попадете на работу функции hello,
а вот так вас не контроллер не пропустит:
example.com/?action=inner
примеров использования таких контроллеров масса — все ограничено лишь вашей фантазией, они успешно заменяют swich и каскады if-else, обеспечивают понятный слой абстракции, достаточно быстры и легко расширяемы.
дальнейшее развитие идеи таких контроллеров лежит в использовании наследования, например если вы узнали что ваш пользователь зарегистрирован, то ничего вам не мешает создать класс для зарегистрированных
и при создании объекта писать:
тогда для авторизованных пользователей будет использован уже класс UserExampleModule для создания объекта module, в котором контроллер будет искать функцию.
в целом это все о чем я хотел рассказать ^_^, дальше расскажу уж просто про идею этого метода.
в первые я «изобрел» это колесо еще 2 года назад (для себя, хотя мир знал это давненько), тогда же оказалось, что такой подход используется некоторыми западными авторами-программистами, до сих пор я вижу тонны кода, в которых не используются даже простые контроллеры на найминге, вместо этого почему-то программистов прельщает писать ОГРОМНЫЕ swich, призываю вас так не поступать -), надеюсь вам этот топик поможет.
всем спасибо, не судите строго!
Часто используют функциональные контроллеры, основанные на найменге (naming) примеры всем широко известны, например плагины смарти:
smarty_type_name() как видите из документации, плагин становится доступным если объявлены соответствующие функции.
в целом там простой контроллер который ищет функцию по простым правилам, основанных на именовании.
часто такие вызываемые сущности хочется проинкапсулировать или иначе собрать и закрыть во что-либо, в результате появляются файлы с типично функциональным подходом:
mylib.php:
function mylib_afunc(){}; function mylib_bfunc(){}; function mylib_cfunc(){};
конечно, это не гарантирует целостности, засоряет глобальное пространство имен и проч.
Удобно такие вещи проинкапсулировать в класс:
class MyLib{ static function a(){}; static function b(){}; static function c(){}; }
далее не сложно понять как нужно сделать контролер, основанный на method_exists, которому первым аргументом вполне можно давать имя класса-контейнера. Как правило, на этом фантазия останавливается, но из объектной парадигмы можно извлечь еще много различных выгод:
- Используя наследование можно иметь «расширения» наборов таких вызываемых сущностей
- Используя полиморфизм + наследование можно переопределять необходимые функции для тех или иных сущностей
- Ограничение видимости поможет скрыть внутреннюю реализацию, которая должна быть скрыта от контроллера.
перейду к рассмотрению сразу же конкретной задачи, чтоб на примере было проще понять идею.
хотим реализовать простой контролер выбора отображаемой страницы модуля.
для начала покажу самый дурной вариант того как это делают:
swich $_GET['action']{ case: "a" ... case: "b" ... case: "c" ... }
хуже только варианты с if-elseif-else, чтоб такого не было пишут контроллер, например, как в смарти, основанный на найменге:
if (function_exists('myAction_'.$_GET['action'])) call_user_func('myAction_'.$_GET['action']);
но я опишу немножко другой подход, более формальный:
тут код в цвете: dumpz.org/2513
а тут просто код, чтоб не бегать:
abstract class Module { public final function buildPage($action) { do{ //нельзя вызвать функции, начинающиеся с подчеркивания //(общепринятое соглашение считать их приватными) if (substr($action, 0, 1) == '_' or empty($action)) break; //нельзя вызвать функции описанные в абстрактном классе, они для работы системы if (method_exists(__CLASS__, $action)) break; if (!method_exists($this, $action)) break; $method = new ReflectionMethod($this, $action); //доступны только публичные методы if (!$method->isPublic()) break; return $this->$action(); }while(false); return $this->error404(); } public function error404(){ echo 'такой страницы нет в системе'; } } class ExampleModule extends Module{ function hello(){ echo 'hello World!'; } function test(){ echo 'Тест!!!'; } protected function inner(){ echo 'это внутренняя функция не доступна контроллеру!'; } } $module=new ExampleModule(); $module->buildPage(isset($_GET['action'])?$_GET['action']:'');
контроллером является функция "buildPage"
таким образом если вызвать скрипт
example.com/?action=hello
то попадете на работу функции hello,
а вот так вас не контроллер не пропустит:
example.com/?action=inner
примеров использования таких контроллеров масса — все ограничено лишь вашей фантазией, они успешно заменяют swich и каскады if-else, обеспечивают понятный слой абстракции, достаточно быстры и легко расширяемы.
дальнейшее развитие идеи таких контроллеров лежит в использовании наследования, например если вы узнали что ваш пользователь зарегистрирован, то ничего вам не мешает создать класс для зарегистрированных
class UserExampleModule extends ExampleModule { function hello(){ echo 'привет зарегистрированный пользователь!'; } }
и при создании объекта писать:
if (проверка авторизации) $module=new UserExampleModule(); else $module=new ExampleModule();
тогда для авторизованных пользователей будет использован уже класс UserExampleModule для создания объекта module, в котором контроллер будет искать функцию.
в целом это все о чем я хотел рассказать ^_^, дальше расскажу уж просто про идею этого метода.
в первые я «изобрел» это колесо еще 2 года назад (для себя, хотя мир знал это давненько), тогда же оказалось, что такой подход используется некоторыми западными авторами-программистами, до сих пор я вижу тонны кода, в которых не используются даже простые контроллеры на найминге, вместо этого почему-то программистов прельщает писать ОГРОМНЫЕ swich, призываю вас так не поступать -), надеюсь вам этот топик поможет.
всем спасибо, не судите строго!