Как преобразовать страничное PHP-приложение в MVC?

Я уже некоторое время борюсь с тем, как именно перекодировать PHP-приложение на основе страниц с использованием среды MVC. Просто для фона мне нужно переместить приложение в MVC, потому что мой босс заставляет меня. Так или иначе, я сел и распечатал структуру каталогов. Затем я начал пытаться спланировать, как я могу преобразовать эти страницы в пары контроллер/действие. Некоторые вещи кажутся очень прямыми. Например, у меня была пара страниц, посвященных добавлению/редактированию/удалению пользователя. Очень просто создать «пользовательский» контроллер и добавить методы или действия для добавления/редактирования/удаления. У меня возникают проблемы, когда я решаю, когда на самом деле создавать контроллер, а когда делать что-то просто действие, поскольку это не всегда так однозначно. Например, контроллер входа в систему по сравнению с пользователем/логином или контроллер регистра по сравнению с пользователем/регистром. На мой взгляд, если объект может что-то сделать, вполне логично быть действием, но это не всегда так однозначно.

Другой пример: у меня есть около 12 страниц форм, которые используются для создания «плана». В моей голове я бы подумал, что мне нужно создать контроллер «плана», и каждая из старых страниц for станет действием. Так что у меня был бы один контроллер с 12 действиями (методами). Проблема для меня в том, что, хотя все эти 12 страниц являются формами ввода данных, которые в конечном итоге составляют этот «план», это все, что у них общего. Каждая из страниц использует разные таблицы в базе данных и не имеет ничего общего друг с другом. По сути, создавая контроллер «плана», я действительно использую его как механизм группировки; не обязательно использовать его, потому что они имеют что-то связанное друг с другом. По крайней мере, в приведенном выше примере «пользовательского» контроллера; каждое из этих действий использует одну и ту же «пользовательскую» таблицу, поэтому имеет смысл сгруппировать эти действия в один контроллер. Должен ли я сделать каждую из этих форм ввода данных собственным контроллером?

Я предполагаю, что это просто сводится к тому, чтобы позволить себе использовать контроллеры в качестве сущности иерархической структуры вместо объектов/действий. Просто кажется, что очень легко попасть в эту ловушку, неправильно используя контроллеры. Кто-нибудь понимает, что я говорю? Надеюсь, это не слишком запутанно.

EDIT: если я попытаюсь придерживаться одного контроллера для каждого представления; Затем я буду сводить код для каждого запроса к минимуму. Это лучший способ?

EDIT: Из того, что все говорят, кажется, что один контроллер на представление не будет в моих интересах. У меня все еще есть некоторые опасения, потому что кажется, что контроллер может быстро стать толстым, но это для другого обсуждения. У меня также все еще есть некоторые проблемы, связанные с тем, когда принимать решение об использовании контроллера вместо действия. Хорошим примером может быть само переполнение стека. В верхней части страницы у вас есть выбор «Вопросы», который, как мы можем предположить, приведет вас к контроллеру «вопросов». Я говорю это, потому что с правой стороны вы можете выбрать «Задать вопрос», URL-адрес которого указывает на «вопросы/спросить». Это имеет смысл, что вы используете метод ask контроллера вопросов. Что меня смущает, так это то, что у вас есть опция «Без ответа» в меню. Похоже, у этого есть контроллер для себя. Почему бы просто не выполнить действие под контроллером вопросов, как в «вопросы/без ответа»? Вот где вещи становятся мутными для меня.


person Joe    schedule 06.01.2009    source источник
comment
Я действительно надеюсь, что это требование связано с тем, что они планируют делать большие вещи с этим приложением в будущем, а не просто потому, что MVC — последнее модное слово разработчиков. Если они делают это просто так, это огромная трата времени и может создать массу новых ошибок.   -  person TravisO    schedule 07.01.2009
comment
я думаю, что этот джокер (джо) слишком много мета и недостаточно сделать   -  person    schedule 12.01.2009


Ответы (11)


так как ваш босс любит модные словечки, скажите ему поискать "рефакторинг"

person Community    schedule 06.01.2009

Немного не по теме вашего вопроса... ради всего святого, не забывайте свои старые URL-адреса. Причина в том, что в ту минуту, когда вы щелкаете выключателем на новом сайте и его красивых URL-адресах, весь совокупный контент, хранящийся в поисковых системах, медленно истечет, что приведет к снижению вашей SEO-статистики.

ОБНОВЛЕНИЕ: Если я попытаюсь придерживаться одного контроллера на представление... тогда я буду сводить код на запрос к минимуму, но лучший ли это способ?

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

Фреймворк «MVC», с которым я имел дело, который делал один контроллер для просмотра, быстро превратился в запутанный беспорядок с множеством хаков и спагетти-кодом.

У меня есть около 12 страниц форм, которые используются для создания «плана».

Мне приходилось делать что-то подобное и, как бы глупо это ни звучало, вероятно, лучше всего иметь контроллер «planningform». Да, есть несколько таблиц для подачи, но вы можете делать простые вещи, такие как $_SESSION['plannerController']['subject|action'][key][value], чтобы контролировать каждую часть формы в целом. Использование каждого метода для обработки части многостраничной формы также может быть преимуществом (например, что, если ваш начальник скажет, что им нужно только 6 из 12 страниц, или что, если часть 7 станет действительно сложной и потребует таких вещей, как автозаполнение ajax).

Механизм группировки не обязательно его использует, потому что они чем-то связаны друг с другом.

Обычно мне нравится парадигма «один класс, одна цель», но иногда просто нет смысла пытаться это сделать. Бывают случаи, когда его четкая огранка прямо из учебника OO, а в других случаях академическая BS может пойти к черту. Вы найдете вещи, которые не соответствуют шаблону OO, поэтому вы можете сделать шаг назад и попытаться объединить вещи в общие категории.

person David    schedule 07.01.2009

Какой смысл иметь одно представление на контроллер?

Снова:

  1. Вы не загружаете больше кода, чем необходимо для каждого запроса. Вы бы загрузили библиотеку, пакет, dll, которые вам не нужны? Конечно, нет. Поэтому не создавайте массивный файл контроллера, в котором для каждого запроса будет выполняться только небольшая часть кода. Кроме того, файлы меньшего размера легче поддерживать imo, как и методы меньшего размера и модульный код.
  2. существует четкая связь 1:1 между контроллером и представлением (особенно если они имеют одно и то же имя). Это соглашение. Это ясно и последовательно. Если я смотрю на шаблон представления, я точно знаю контроллер, который загружает его, основываясь только на имени файла. В этом нет никакого мышления. Никаких решений. Никаких компромиссов.

Какая необходимость в разделении интересов, когда все просто совмещается попарно?

Какая необходимость в разделении интересов? Если вы хотите сгруппировать связанные страницы (контроллеры/представления), объедините их в каталоги.

Я был бы более склонен написать контроллер, который управляет несколькими представлениями, которые каким-то образом связаны. Например, вышеупомянутое добавление/просмотр/редактирование пользователя. Вы бы хотели сохранить схожие функции вместе, а не искать во многих файлах код, который вам нужен. Также удобно иметь все методы, определенные (для конкретного объекта) в одном месте. НАМНОГО упрощает обслуживание.

Я почтительно не соглашусь. Если у меня есть одно представление, которое отвечает за добавление/просмотр/редактирование пользователя, то с соглашением 1:1 я точно знаю ответственного контроллера. С другой стороны, используя ваше предложение сгруппировать аналогичные функции, если у меня есть контроллер менеджера и контроллер пользователя, какой из них содержит добавление/просмотр/редактирование для менеджера? Пользователь или менеджер? Теперь надо думать или искать.

Я работал над проектом, используя структуру PHP, которая создавала отдельный файл для каждого «действия». Назван как «объект (действие)», и поддерживать его стало КОШМАРОМ.

Я не предлагаю это.

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

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

Мой единственный совет: не пытайтесь организовать свой проект на основе какого-то идеала MVC. Организуйте свой проект так, как это имеет смысл для вас и вашего домена.

Нет нет нет. Это очень опасный совет. Шаблоны проектирования, соглашения по кодированию и фреймворки были разработаны с определенной целью — лучшими практиками и согласованностью. Только гуру должен выходить за рамки условностей и только в том случае, если он/она работает в одиночку. Даже в рамках фреймворка я постоянно стремлюсь к большей согласованности, чтобы мне не приходилось думать при написании или сопровождении кода.

person rick    schedule 08.01.2009

Делая такой шаг, вы не просто меняете реализацию конкретного сайта, но, скорее, меняете способ его восприятия. Вам все равно придется перекодировать изрядно, но у вас есть преимущество в понимании концепции и наличии опыта в том, как это сделать.

Мое предложение было бы сесть и притвориться, что вы ничего не знаете о том, как реализовать сайт, но все о том, какие проблемы связаны с сайтом, над которым вы работаете, его требования и его подводные камни. Создайте концепцию сайта на основе MVC, а затем попытайтесь повторно использовать как можно больше кода, который у вас есть. Повторное использование кода в конечном счете может оказаться неосуществимым, но с другой стороны, по крайней мере, вы решали многие из тех же проблем раньше, поэтому реализация не займет много времени.

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

person Robert Elwell    schedule 06.01.2009

Какой смысл иметь одно представление на контроллер? Какая необходимость в разделении интересов, когда все просто совмещается попарно?

Я был бы более склонен написать контроллер, который управляет несколькими представлениями, которые каким-то образом связаны. Например, вышеупомянутое добавление/просмотр/редактирование пользователя. Вы бы хотели сохранить схожие функции вместе, а не искать во многих файлах код, который вам нужен. Также удобно иметь все методы, определенные (для конкретного объекта) в одном месте. НАМНОГО упрощает обслуживание.

Я работал над проектом, используя структуру PHP, которая создавала отдельный файл для каждого «действия». Назван как «объект (действие)», и поддерживать его стало КОШМАРОМ.

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

Мой единственный совет: не пытайтесь организовать свой проект на основе какого-то идеала MVC. Организуйте свой проект так, как это имеет смысл для вас и вашего домена. MVC был предложен для ограничения сложности, а не для ее увеличения.

Для вашего примера плана я бы превратил это в контроллер. www.example.com/plan/1 .. /plan/2 и т. д. Это имеет смысл, потому что действия логически сгруппированы вместе, чтобы сформировать некоторую задачу.

Контроллер, на мой взгляд, должен использоваться для управления задачей или объектом. Его методы должны быть конкретными действиями, необходимыми для выполнения этой задачи или изменения/использования объекта.

person Josh Smeaton    schedule 07.01.2009

Я прошел через подобное в прошлом году. Я преобразовал свои в основном статические страницы веб-сайта PHP для использования Kohana PHP Framework. Я сделал каждый раздел веб-сайта контроллером с представлениями для отдельных страниц. Представления главной страницы включали другие представления для верхнего и нижнего колонтитула. Некоторые из представлений, например, для статей, можно было повторно использовать разными контроллерами. Результатом стал сайт MVC с теми же URL-адресами страниц, что и исходный веб-сайт.

РЕДАКТИРОВАТЬ: URL-адреса имеют формат /controller/method?arguments. Например, на моем сайте URL для /computer/article.php?id=# использует функцию article в контроллере computer. Контроллер computer, в свою очередь, использует модель статьи для загрузки данных в представление статьи с вложенным абзацем. взгляды. Это также показывает, что даже несмотря на то, что предыдущая версия сайта имела имена страниц с расширением .php в URL-адресе, это все еще может быть преобразовано в метод класса контроллера, и тот же URL-адрес работает в версии сайта на основе MVC. Это должно дать вам представление о том, как Kohana может работать на вашем сайте.

person Tim Butterfield    schedule 08.01.2009

У меня также все еще есть некоторые проблемы, связанные с тем, когда принимать решение об использовании контроллера вместо действия. Хорошим примером может быть этот веб-сайт stackoverflow. В верхней части страницы у вас есть выбор «Вопросы», который, как мы можем предположить, приведет вас к контроллеру «вопросов». Я говорю это, потому что с правой стороны вы можете выбрать «Задать вопрос», URL-адрес которого указывает на «вопросы/спросить». Так что имеет смысл использовать метод ask контроллера вопросов.

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

Кто знает. Но учтите следующее: страница «Вопросы» потребует в несколько раз больше кода, чем страница «Задать вопрос». Имеет ли смысл загружать код страницы «Вопросы» при загрузке страницы «Задать вопрос». Я думаю, ребята из stackoverflow будут умнее.

Но что меня смущает, так это то, что в меню есть опция «Без ответа». Похоже, у этого есть контроллер для себя. Почему бы просто не выполнить действие под контроллером вопросов? Как в "вопросы/без ответа"? Вот где вещи становятся мутными для меня.

Еще одна причина, по которой я думаю, что страница «Задать вопрос» имеет собственный контроллер. Страница «Вопросы» имеет гораздо больше общего со страницей «Неотвеченные».

person rick    schedule 08.01.2009

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

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

Было ли это из-за фреймворка, разработчика или того и другого? Насколько сложно было поддерживать? Какие взломы были задействованы и почему?

У меня хорошо работает 1 контроллер на 1 представление в фреймворках php MVC Zend, CodeIgniter и Kohana. В ASP.NET, хотя и не в MVC, 1 веб-форма/представление сопоставляется с 1 кодом позади файла.

person rick    schedule 08.01.2009

Вся концепция стала для меня более ясной после серии из трех сообщений в блоге Nemetral, которые объясняют шаблон, поскольку он развивается из традиционного сценария веб-страницы и, таким образом, как логика PHP становится отдельной от логики представления, таким образом, с точки зрения MVC, как модель становится отдельной от взгляда. Согласно Неметралу:

  1. Первый шаг — переместить весь PHP-код, который до сих пор был связан с HTML-тегами, в заголовок страницы.
  2. Второй шаг — переместить все теги HTML в отдельный файл и получить к нему доступ через включение PHP. Поэтому, когда делается запрос, он направляется в код PHP (контроллер и модель), и этот код затем запрашивает теги HTML или представление (представление).

Подробнее об этом я пишу в своей диссертации: http://kreus-cms.com/kreus/pages/writing_work

person Radek    schedule 12.05.2009

Предполагая, что у вас есть какие-то тесты, охватывающие большую часть (все?) функциональности вашего приложения.

  1. Детализируйте действительно базовую структуру того, как будет выглядеть ваша С-часть.
  2. Реализуйте эту структуру, игнорируя M и V, более или менее просто копируя фрагменты кода из ваших файлов, ориентированных на страницы, в ваши контроллеры.
  3. Проверьте, все ли работает так, как ожидалось.
  4. Пройдитесь по каждому контроллеру, извлеките «M» и «V». «M» может быть просто Active Record (я знаю, что это не настоящая модель) или шлюзом таблицы строк или чем-то, что довольно быстро реализовать. Теперь контроллер должен становиться все тоньше и тоньше
  5. Проверьте, все ли работает так, как ожидалось.
  6. Теперь, когда вы знаете все о своем приложении, снова выполните рефакторинг, чтобы извлечь модель предметной области, если это применимо. В некоторых случаях это может быть просто пустой тратой времени (только для CRUD/интенсивных приложений).
  7. Проверьте, все ли работает так, как ожидалось.
person user105719    schedule 12.05.2009

Где у меня больше всего проблем, так это решить, когда на самом деле создавать контроллер, а когда делать что-то просто действие, потому что это не всегда так однозначно.

По возможности используйте один контроллер для каждого представления. Туда:

  1. вы не загружаете больше кода, чем необходимо для каждого запроса
  2. существует четкая связь 1:1 между контроллером и представлением (особенно если они имеют одно и то же имя).
person rick    schedule 06.01.2009
comment
Я думал об этом ... но из всех примеров, которые я вижу в Интернете, я редко вижу, как это делается. Особенно в ROR, где у контроллера может быть 5-10 и более методов. Я согласен, что странно размещать так много кода в контроллере, который будет использовать только небольшую его часть при каждом запросе. - person Joe; 07.01.2009
comment
Некоторые из моих контроллеров имеют более 10 публичных методов действий. Зависит от того, сколько действий в представлении. - person rick; 08.01.2009