Pull to refresh

Comments 24

мне кажется, что вы в два года назад «изобрели» третью букву в слове MVC :)
зато читать было интересно, спасибо
контролеры давно придуманы как таковые, а вот использование в PHP их я думаю начал с первыми. я же написал что изобрел колесо — эта методика была давно известна, просто у нас о ней мало пишут.
мне просто показалось, что приведенная проблема решилась бы если писать проект с использованием паттерна mvc, я не прав?
тогда с интересом жду продолжения темы с развитием про наследование и полиморфизм
ну не знаю, я постарался придумать пример достаточно законченым с одним контроллером, без представления и модели, ее я оставил за рамками.
1. А инстанцирование нужного модуля вы на контроллер не возлагаете? Тогда вы не избавляетесь от swich, а просто уменьшаете его размер (нужно будет выбирать только модуль). Почему не вынести контроллер в отдельный класс и не проверять точно так же class_exists и проверять публичность меода через is_callable?

2. А где исходник самого ReflectionMethod? Мне пока не совсем понятно зачем он вообще нужен.

3.
>> if (проверка авторизации)
>> $module=new UserExampleModule();
>> else
>> $module=new ExampleModule();
Совсем уж как-то дико выглядит. Намного проще/понятней закрывать доступ к отдельным функциям или модулям. Если же необходимо разное поведение для (не)зарегестрированного пользователя, то проверять авторизацию уже в самом модуле и из одного и того же public метода вызывать разные private/protected
по поводу пункта 2:
ReflectionMethod — нативный класс PHP служит для анализа метода класса.

по поводу пункта 1: я же тут не привожу реализацию MCV я показываю как контроллер можно построить это просто пример.

по поводу пункта 3: acl давно существует, но это другой метод, мне этот более понятен, кода видно то, что может быть использовано, а не ситуация, когда есть ресурсы, которые закрыты.
1. Просто если мы определяем какой метод вызывать, то теряется сам смысл рефлексии. Она ведь нужна только потому что из текущего класса все is_callable. А так это смотрится не как пример построения контроллера, а как слегка надуманный пример использования рефлексии, за что спасибо.

2. Спасибо. Как-то упустил это расширение. Кстати, в вашем случае, его может заменить и своим классом )

3. Так и я не про acl говорю. ACL, по сути, не навязывает где должна проходить проверка прав доступа. При использовании вашего метода, где имеено и на каком этапе вы будете определять какие нужно инстанцировать как User* а какие нет?

При таком контроллере + огрничении доступа воображение рисует index.php вида:
swich($module) {
   case 'blog':
      if (User::isAuthenticated()) 
       $module = new UserBlogModule();
    else
       $module = new BlogModule();
     }
}
if ($module) {
   $module->buildPage('action');
}

Немного неудобно, не правда ли?
да я понял вас, вы, конечно, правы, в идеале нужно написать фабрику в самом абстрактном модуле, которая будет выбирать тип создаваемого модуля (в зависимости от ролей)
/**
@return Module
**/
static function fabrica($moduleName)…

реализация ее проста, но специфична для задачи в приведенном выше примере она будет наподобии:
static function fabrica($moduleName){
    if (User::isAuthenticated() and class_exists("User".$moduleName)  and is_a("User".$moduleName, "Module") ) {
         $moduleName="User".$moduleName;
    }elseif(!is_a($moduleName, "Module")){
          return null;
    }
    return new $moduleName;
}


как видите теперь вообще можно писать:
$module=Module:: fabrica($GET['module']);

и ни о чем не думать, вообще я планирую однажды написать о том как я реализую полный контроллер для создания страниц на этой идеалогии, он решает многие задачки и сильно упрощает жизнь, но статья посвящена именно тому как классы и рефлексию использовать в контроллере, а не тому как писать контроллер или реализовать MCV, но всеже забежав немного в перед я, надеюсь, ответил на ваш вопрос ;-)
Мне понравилось с function_exists… Но надо не забывать, что $_GET['action'] нужно отфильтровать на спецсимволы — безопасность всегда важна :)
Конечно важна, но, скажите, вы можете привести пример строки, которая может вызвать сбой при передаче в function_exists? )
тут действительно не нужно париться с верх меры, ведь я рассказал о том как писать контроллер, привел такой пример, а вообще такие контроллеры удобно использовать в событийной модели разбора XML документов например, когда метод реагирует на отведенный ему XML тег, да масса примеров, SAOP так делал — удобно выходило, RPC тудаже, в целом статья о контролллере.
То есть, так можно вызывать любой публичный метод контроллера? Ой как нехорошо. Как минимум потому, что неплохо бы разделять экшны по типу запроса (GET/POST/POST+AJAX).

А вот если добавить немного нейминга:
function GET_a()
function POST_b()

и т.д. в том же духе, то по-моему будет ближе к идеалу
> То есть, так можно вызывать любой публичный метод контроллера? Ой как нехорошо.
А что в этом плохого? Ведь можно вызвать метод не любого класса, а только некоторых.

А разделение по get/post/xmlhttprequest это уже дело вкуса. Зачастую нужно переключать только view а, значит нет неоходимости в таком разделении.
на практике найминг очень полезная вещь, я хотел показать, что есть методы отличные от найминга =)
разделять экшны по типу запроса не советую просто потому что часто это не нужно, но в целом идею принял, мне понравилось, действительно можно сделать чтоб сначала искалась функция
function POST_b()
если ее нет, то
function b(), так, пожалуй, иногда может пригодиться, но редко… как правило функция делает одно и тоже а от типа запроса зависит тип ответа всего лишь, либо это JSON (POST+AJAX), либо кусок страницы (обновляемый тупо AJAX) или это вся страница. эта работа ложится на другой слой вообще говоря на слой Viewer в патрене MVC и к контроллеру имеет слабое отношение, тоесть метод (action) отработав дает результирующие данные, а они уж идут либо в один либо в другой шаблонизатор.

Если действительно есть интерес посмотреть как сделать систему для сайта, то могу написать именно про это, там много подводных камней.
Меня беспокоит только то, что можно дернуть любую функцию и любым методом. Ну неструктурно это.

А про систему — пишите, интересно. :)
ну тут двояко… вот есть у вас форма поиска, которая может получать доп параметры, а может не получать их и какая разница

? do=search вы просто урлом передаете или хидден параметром формы поиска? в принципе без разницы. ну может не структурно, хотя я не понимаю. назовите причину по которым такие вещи нужно разделить и я, быть может, пойму о чем вы.
1. методы должны иметь префикс: $this->do_*(), act_*, do_step* для безопасности и выделения.

Фактически такой подход конечно, служит автоматизации. Не надо писать несколько строк. И можно расширять контроллер без изменения конструктора. Но по моему, методы $this->*() должны вызываться с определёнными параметрами (из GET/POST/*), или до вызова определённого метода должны устанавливаться переменные среды (т. е. $this->SET1, $this->set2['param1']).
И такой подход имеет право только при сходных страничках ($this->do_step_*()).
Интересный способ do {} while(false);
Я все время пользовался try {} catch () {}
экспешены просто медленее (ну покрайней мере у меня такое убеждение осталось) + не так читаемо (нет гарантий перехвата).
Sign up to leave a comment.

Articles