MVC в PHP без "магии" - PullRequest
       193

MVC в PHP без "магии"

1 голос
/ 15 ноября 2009

Допустим, у меня есть платформа PHP Model-View-Controller, которая отображает адрес, подобный http://example.com/admin/posts/edit/5, в действие, которое выглядит как

Posts_Controller::editAction($id)

в файле /admin/controllers/posts.php

Сейчасмногие существующие PHP-фреймворки, на которые я смотрел, достигли бы этого с помощью чего-то вроде

$module = Router::getModule(); // "admin"
$controller = Router::getController(); // "posts"
$action = Router::getAction(); // "edit"
$params = Router::getParams(); // array(5)

$controller_file = "/".$module."/controllers/".$controller.".php";
$controller_classname = ucfirst($controller)."_Controller";
$method = $action."Action";

require_once $controller_file;
$controller_obj = new $controller_classname();
call_user_func_array(array($controller_obj,$method),$params);

Для меня это пахнет плохо и кажется слишком «волшебным»: я не верю, что вы должны быть в состояниичтобы динамически создавать классы на основе строки, а затем вызывать методы, указанные в ней как строки.

Я также видел альтернативы, использующие отражение для вызова действий, что также плохо пахнет.

Теперь представьтеУ меня есть более крупная модульная CMS, построенная из аналогичной инфраструктуры MVC, в которой есть таблица в БД для каждого типа «страницы»: блог, статика, фотоальбом и т. Д. Я думаю, что реализация для этого похожа намой предыдущий пример.

Я единственный, кто считает, что это плохо?Если нет, то не должен ли быть шаблон проектирования, который бы охватил эту ситуацию?

Чтобы уточнить:

Есть ли какой-нибудь хороший способ сопоставить запрос, содержащий информацию омодуль, контроллер, действие и параметры в

  1. Файл для включения
  2. Класс для создания экземпляра
  3. Метод для вызова '

Это использует как маленький"магию" (от строки к классу, или к методу, или к отражению), насколько это возможно?

Еще лучше: как это будет сделано в C # или Javaбез размышлений?Я могу разрешить объединение строк в файл.

Ответы [ 7 ]

7 голосов
/ 15 ноября 2009

Это было бы обработано каким-то фабричным шаблоном, PHP просто делает хороший синтаксический сахар, чтобы избежать всей реализации вокруг фабричного шаблона. Я не думаю, что это вообще волшебство, это просто использование языка.

5 голосов
/ 15 ноября 2009

На самом деле здесь два вопроса.

  1. Является ли PHP как язык, используемый здесь правильно.
  2. Является ли логика этого кода слишком "волшебной"

Я могу высказать свое мнение об этом как о PHP-разработчике и инженере-программисте, который занимается разработкой веб-приложений, в основном на основе некоторой инфраструктуры MVC

1) Каждый язык имеет собственный синтаксис, который обеспечивает более или менее выразительную выразительность. Я согласен с тем, что вся мощь одного языка не должна использоваться в каждой строке кода для удобства чтения и простоты. Но в этом случае, когда ядро ​​MVC спроектировано и реализовано, я не вижу причин не использовать их, особенно в тех местах, где конечный пользователь (в этом смысле разработчик приложения) не видит этой магии, если он хорошо инкапсулирован. Я предполагаю, что это упрощенный и вычеркнутый фрагмент, который вы разместили, поскольку должны быть некоторые другие соображения относительно его дизайна, но создание нового экземпляра на основе имени строки и вызов функции аналогичным образом - это обычный подход в мире PHP.

2) Я согласен, что этот код логичен, в некоторой степени волшебен, особенно потому, что он, вероятно, дает обещание универсальности для разработчика. В этом отношении существуют разные подходы, которые в большинстве случаев снижают универсальность решения и предоставляют некоторые средства прямого определения отображения с помощью карты команд или аналогичного подхода (например, БД, как вы сказали). Таким образом, магия находится в руках разработчика. Как правило, это не подходит для быстрой разработки, так как при настройке отображений, которые волшебством маршрутизатора в вашем случае автоматически разрешается, много ручного труда.

Надеюсь, это немного поможет.

Ура, Иван

1 голос
/ 15 ноября 2009

Я не верю, что ты должен быть возможность динамически создавать классы основанный на строке, затем вызвать методы на нем указаны в виде строк.

Это кажется произвольной вещью, которую мы "не должны" делать?

Магия, о которой вы говорите, это просто абстракция. Вы (надеюсь!) Уже используете все виды абстракций в своей повседневной работе.

Так как насчет этой конкретной абстракции, которую вы не одобряете?

Я действительно думаю, что лучший ответ на этот вопрос: преодолеть его и вернуться к работе! : -)

1 голос
/ 15 ноября 2009

Я не знаю, на какие рамки вы смотрели. Те, которые я использовал до сих пор (CodeIgniter и Yii), работают магически, но имеют гарантии. Например, все контроллеры должны быть расширены из класса Controller, поэтому вы не можете создать экземпляр любого класса , только контроллер. При использовании CodeIgniter рекомендуется объявить все методы контроллера, которые не должны быть доступны через браузер, закрытыми. Yii переносит это на другой уровень, требуя, чтобы все такие методы начинались с «action» (это будет «actionEdit» в вашем примере), так что вы действительно не можете вызвать какой-либо произвольный метод извне.

Я считаю, что вся эта магия очень полезна, когда в команде несколько разработчиков, потому что она гарантирует, что люди следуют правилам, и намного легче проникнуть в код друг друга и понять, что происходит. Без применения таких соглашений вы должны тратить время на отслеживание браузера, какая ссылка ведет куда, а затем копаться в PHP-коде, чтобы найти, куда он идет. Это может превратиться в большую неразбериху с таким рыхлым языком, как PHP (без строгих типов, переменных, объявленных при первом использовании, динамических массивов и т. Д.). В C # или Java это язык, который обеспечивает порядок, в PHP это работа для фреймворков.

0 голосов
/ 26 ноября 2014

Я немного сбит с толку относительно того, что вы подразумеваете под MVC? Мое понимание может помочь. Моя плита, шкаф и холодильник функционируют как контроллеры в системе MVC, где моя еда и ингредиенты являются объектами данных, а то, что я положил на тарелку на обед, является видом. MVC - это просто парадигма кодирования. Вы можете применить это к чему угодно.

Я не пытаюсь уклониться от вопроса; Я просто чувствую, что мой ответ будет неполным. Я чувствую, что вы действительно спрашиваете: «Как я могу точно реализовать ту же функциональность, что и существующая инфраструктура, которая делает MVC-кодирование простым», или, если коротко, «как я могу делать то, что MVC-инфраструктура делает более чисто». И если это то, что вы просите, я боюсь пропустить большую часть, я боюсь.

Таким образом, искажение URL-адресов, на мой взгляд, будет включать программные манипуляции со строками. Я собираюсь полностью избежать этой части вашего вопроса. Это «большая часть», которую я упомянул.

Но «как я могу передавать сообщения свободно определенному объекту, как это делает Apple, сделавшая термин MVC знаменитым», я считаю, что к этому можно обратиться напрямую. Я бы сделал это с интерфейсами и диспетчерским "крючком",

 abstract class Message {
   // has a bunch of info about the current program state as properties,
   // retrieved from e.g. $_POST or the db,
   // and ways to retrieve that info automatically as methods named after the channel
   // they pull information from,
   // the constructor is responsible for using these methods
   // so they should be protected
 }

 interface Action {
   // now we know enough about a message to handle it in an abstract way,
   // no array mapping etc.
   function doSomething($Message);
 }

 /** do this up the same way it exists in the database */
 abstract class ModelObject {
   public $fields = array();

   // I am a linked list
   public $next = NULL;
   public $prev = NULL;

   // constructor that takes a primary key as an argument and pulls stuff
   // from the DB with it
 }

 /** this has a predictable name known to the Main application controller */
 hook_do_stuff() {
   $state = new DoStuffMessage();
   $user = new User(); // User is a ModelObject

   // maybe there is even an Admin ModelObject that can use $user in its constructor?

   // decide how to handle things in an abstract way here,
   // maybe even run tests on the URL as it is now just another piece of
   // program state information
 }

После этого проведите множество тестов function_exists, и вам будет хорошо. Я думаю, вы обнаружите, что этот подход легко реализовать где угодно. Это немного сложно в таких языках, как Java, где hook_do_stuff () не может быть объектом первого класса, но до тех пор, пока вы рассматриваете любой класс, в котором есть метод main (), как «глобальную» область видимости, он все еще выполним.

В противном случае, надеюсь, я не понял неправильно, о чем вы действительно просили?

0 голосов
/ 15 ноября 2009

Похоже, у вас проблемы с магией ORM, а не с MVC, которая является просто маглом.

0 голосов
/ 15 ноября 2009

Для большинства вещей, над которыми я работал, среда MVC кажется слишком раздутой.

Я предпочитаю использовать шаблонизатор, например, smarty ( www.smarty.net )

Вы по-прежнему получаете такое же разделение кода и представления. Я считаю, что это создает более аккуратную организацию кода, где вы управляете всеми файлами и структурой каталогов. Код можно сгруппировать логически, а не по страницам.

...