Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > логика MVC


Автор: g27 6.2.2013, 09:21
Здравствуйте, практикуюсь с MVC. Допустим на странице отображается список товаров скажем. Так вот, маршрутизация определяет, что необходимо вызвать контролер товаров и их модуль. Контроллер товаров получает данные из модуля, отображение приводит их в нужный вид и на выход.  Помимо этого на странице может находится много другой информации. Начиная меню пунктами, информация о активном пользователе и т.д. Так вот у меня вопрос, теоретически на каком этапе правильно будет это всё обрабатывать? Я так понимаю для генерации меню, должен быть контроллер меню. Но в каком месте и кто его будет запускать? Неужели тот самый контроллер товаров и его метод вывода списка товаров будет инициализировать дополнительные элементы? Мне кажется, что контроллеру товаров не нужно знать о таких вещах. Объясните пожалуйста.

Автор: Arantir 6.2.2013, 09:53
Контроллер должен связывать запрос и итоговый результат. Контроллер - это вам не крышечка бутылочки для каждого вида (view).

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

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

Понятное дело, что прописывать взятие кусочка с меню в каждом контроллере, неудобно. По-этому, на практике часто используют layouts (не знаю как нормально перевести, дословно - макеты). Суть в том, что есть несколько слоев. Например, общий слой, слой контроллера, слой действия. Для удобства все они подхватываются автоматически из заданных папок. При этом сначала берется общий слой, в него вставляется слой контроллера (в том месте где вставлен вывод контента из вида), а потом в это все вставляется слой действия.
Таким образом меню можно расположить в общем слое и оно будет автоматически на всех страницах. А список товаров для слоя контроллера страницы товаров будет на все страницах раздела товаров при любом действии (ну всяких там добавлениях, удалениях и прочих).

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

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

Попробуйте почитать документации к всяким разным фреймворкам. Даже не код, а просто документации, чтобы посмотреть на способы решения всяких проблем с MVC в вебе.

Автор: g27 6.2.2013, 12:47
Arantir, огромное спасибо за Ваш комментарий. Мне кажется я понял, но перескажу на пальцах. Берётся один слой (шаблон можно сказать?), он самый главный. В нём есть скрипты для генерации меню и т.д.. Так же оставлено место куда будет вставляться слой контроллера. В слое контроллера есть тоже информация, которая будет всегда при его вызове, но так же есть и место, куда будет вставляться другой слой, который зависит от выполняемого действия. Думаю я правильно понял.
У меня вот ещё вопрос, по поводу слоя действия. Он должен знать в каком слое контроллера он будет находится? Мне кажется что нет, это должен знать только контроллер, который и определит что должен увидеть пользовать в конечном итоге. да?

Автор: Arantir 6.2.2013, 14:05
В целом все верно.

Вид - это только статичный html и места для вставки данных (что-то на подобии <?=$this->get("some_var")?>), ну еще могут быть циклы для вывода однотипных блоков с массива (постов, новостей) и ничего более. В идеале он должен быть таким, чтобы его понял HTML-верстальщик без малейшего представления про модель.

Слой действия - это так же, как и слой контроллера. Он по-умолчанию берется автоматически. Обычно для этого названия слоев контроллеров имеют имена контроллеров, а слои действий имеют имена действий и расположены в папках с именами контроллеров.
Например:
view/poducts/select.phtml
view/layers/products.phtml
view/index.phtml

Тут пути определяются просто:
1. {view_dir}/index.phtml
2. {view_dir}/layers/{controller_name}.phtml
3. {view_dir}/{controller_name}/{action_name}.phtml

Это все дело вкуса и оправдание цели средствами. Для какого-то сайта-визитки достаточно не более двух слоев, так как адресов глубже чем example.com/controller/ нет. Для большинства сайтов, не являющихся какими-то веб-приложениями/сервисами достаточно вышеописанной 3-слойной схемы. Для более сложных видов могут использоваться автономные вставки мелких слоев (подобных слоям действий).

Конечно же, стоит оставить возможность отключать и изменять слои. Например, если все уже на слоях и первые 2 можно выключить, то можно без особых проблем в  2 строчки добавить вывод только вида действия при запросе к контроллеру через AJAX (у них особый заголовок, гугл в помощь). Один контроллер, а делает сразу 2 дела - для GET выдает страницу, для AJAX только последний слой. Динамическая AJAX-подгрузка готова на 80% практически автоматически.
При хорошем проектировании всегда есть много таких приятных "побочных эффектов".

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

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

В большинстве фреймворков вид будет отрисовываться автоматически, без каких либо действий в контроллере.

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

Автор: g27 6.2.2013, 14:22
Всё понятно. Спасибо, очень помогли! 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)