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

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

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

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

РЕДАКТИРОВАТЬ: Если я попытаюсь придерживаться одного контроллера на представление; Тогда я буду сокращать количество кода для каждого запроса до минимума. Это лучший способ?

РЕДАКТИРОВАТЬ: Судя по тому, что все говорят, кажется, что один контроллер на представление не в моих интересах. У меня все еще есть некоторые опасения, потому что кажется, что контроллер может в спешке толстеть, но это уже другое обсуждение. У меня также все еще есть некоторые проблемы с тем, когда принимать решение использовать контроллер вместо действия. Хорошим примером может служить сам stackпереполнение. Вверху страницы у вас есть выбор «Вопросы», который, как мы можем предположить, приведет вас к контроллеру «вопросов». Я говорю это, потому что с правой стороны вы можете выбрать «Задать вопрос», который URL указывает на «вопросы / спросить». Это имеет смысл, если вы используете метод ask контроллера questions. Меня смущает то, что в меню есть опция «Без ответа». Похоже, у него есть контроллер. Почему бы не было просто действием под контроллером вопросов, как в «вопросы / без ответа»? Вот где у меня все становится мутным.

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

TravisO 07.01.2009 02:50

я думаю, что этот шутник (Джо) слишком много "мета" и недостаточно "делать"

theman_on_vista 12.01.2009 17:20
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
11
2
5 802
11

Ответы 11

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

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

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

Where I am having the most problem is deciding when to actually create a controller vs making something just an action because it's not always so clear cut.

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

  1. вы не загружаете больше кода, чем необходимо для каждого запроса
  2. между контроллером и представлением существует четкая связь 1: 1 (особенно если они имеют одно и то же имя).

Я думал об этом ... но, судя по всем примерам, которые я вижу в Интернете, это редко бывает так, как я вижу. Особенно в ROR, где у контроллера может быть 5-10 методов или больше. Я согласен, что странно помещать так много кода в контроллер, который будет использовать только небольшую его часть при каждом запросе.

Joe 07.01.2009 00:32

Некоторые из моих контроллеров имеют более 10 публичных методов действий. Зависит от того, сколько действий в представлении.

rick 08.01.2009 22:19

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

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

UPDATE: If I try and stick with one controller per view...I will then be keeping code per request to a minimum, but is this the best way?

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

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

I have about 12 form pages that are used to create a "plan".

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

grouping mechanism not necessarily using it because they have something related with each other.

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

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

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

Я работал над проектом, используя PHP-фреймворк, который создавал отдельный файл для каждого «действия». Названный как «объект (действие)», он стал НОЧНОЙ, которую нужно поддерживать.

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

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

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

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

What is the point of having one view per controller?

Очередной раз:

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

What need is there for a separation of concerns when everything is just pair matched?

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

I'd be more inclined to write a controller that controls several views that are related in some way. For instance, the aforementioned add/view/edit of a user. You'd want to keep similar functionality together rather than searching through many files for the code you want. It's also handy to have all the methods defined (for a particular object) in one place. Makes maintenance MUCH easier.

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

I worked on a project using a PHP framework that created a separate file per 'action'. Named like 'object(action)' and it became a NIGHTMARE to maintain.

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

I've been using Django for a little while now which keeps all the models in one file, all the views (controllers) in one file, and the templates (views) separately. [Django isn't MVC but for these purposes let's pretend it is]. This allows you to group together common code in one place and maintenance becomes much easier.

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

My only advice is - don't try to organise your project based on some ideal of MVC. Organise your project how it makes sense to you and your domain.

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

If I understand you correctly, each controller would produce one page. This can be a really bad idea that I've experienced first hand in a maintenance position.

The "MVC" framework I dealt with that did the one controller to view quickly became a convoluted mess with lots of hacks and spaghetti code.

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

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

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

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

I also still have some issues of when to make that decision to use a controller instead of an action. A good example would be this stackoverflow website. At the top of the page, you have a "Questions" selection which we could assume takes you to the "questions" controller. I say this, because on the right hand side you can choose to "Ask a question" which the URL points to "questions/ask". So that makes sense that your using the ask method of the questions controller.

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

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

But what confuses me, is then you have the "Unanswered" option on the menu. It looks like this has a controller to itself. Why wouldn't it just be an action under the questions controller? As in "questions/unanswered"? That's where things become muddy for me.

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

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

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

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

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

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

Другие вопросы по теме