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

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

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

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

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

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

так как ваш босс очень счастлив, скажите ему посмотреть «рефакторинг»,

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

UPDATE: если я попытаюсь придерживаться одного контроллера для каждого представления … я буду держать код за запрос до минимума, но лучший ли это?

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

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

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

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

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

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

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

Еще раз:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Вся концепция была более понятна мне из серии из трех сообщений в блоге Nemetral, которые объясняют шаблон, поскольку он развивается из традиционного сценария веб-страницы и, таким образом, поскольку логика 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» может быть просто активной записью (я знаю, это не настоящая модель) или шлюзом таблицы строк или что-то, что довольно быстро реализовать. Теперь контроллер должен стать тоньше и тоньше
  5. Испытайте, что все работает по-прежнему
  6. Теперь, когда вы знаете все о своем приложении, повторно настройте рефакторинг, чтобы извлечь модель домена, если это применимо. В некоторых случаях это может быть просто пустой тратой времени (CRUD-only / -intensive applications)
  7. Испытайте, что все работает по-прежнему.

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

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

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