контроллер — это специализированная сущность для управления другими сущностями.
Часто используют функциональные контроллеры, основанные на найменге (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, призываю вас так не поступать -), надеюсь вам этот топик поможет.
всем спасибо, не судите строго!