Вроде как понятен принцип MVC, а с другой стороны не понятно зачем разделять Controller и Model, а если разделять, то кто за что отвечает, есть небольшие примеры в интернете, например http://habrahabr.ru/post/150267/ но из них это не понятно, меня интересует пример с базой данных, может кто подскажет, приведет пример на псевдокоде (или как там это называется). Допустим есть регистрация пользователя из данных всего логин и пароль, кто за что должен отвечать, последовательность действий такая: Или ситуация попроще, заход на страницу, которую могут видеть только зарегистрированные пользователи:
Объясняю на пальцах.. MVC - представляет собой бизнес модель, это некий стандарт, по которому последующим поколениям кодеров после тебя будет проще ориентироваться. За меня лучше скажет википедия. Т.е. в контроллере только обработка данных, получаем мы данные в модели, в контроллере обрабатываем. Вот схема. Приведу пример из своего самописного(MVC) велосипеда. Всю партянку кидать не буду, просто разбор с комментариями, момента регистрации. Модель В модели у нас будут только методы, которые каким либо образом получают данные(обычно это любого рода запросы к бд) Код (PHP): //наследуем основную модель, в которой реализовано подключение к дб(можно использовать singleton) и набор функций для работы с дб class Model_User extends baseModel { //таблица с которой работаем(для удобства) private $table = 'users'; function __construct() { parent::__construct(); } //поиск пользователя по user_id public function getUser($login) { return $this->getRow("SELECT * FROM ?n WHERE user_id=?s LIMIT 1",$this->table ,$login); } //добавление нового пользователя public function addUser($array) { $this->query("INSERT INTO ?n SET ?u",$this->table, $array); } } Контроллер(здесь у нас будет только обработка данных и получение данных от юзера, никаких запросов к бд Код (PHP): class Ctrl_User extends BaseController{ //методы-действия, все методы с приставкой Action, будут обработаны по соответствующей ссылке http://site/user/register //где user - это соответствующий контроллер, а register - соответствующий метод, по умолчанию метод будет ActionIndex function ActionRegister() { #проверки post данных и.т.п. # Если нет ошибок, то добавляем в БД нового пользователя if(empty($this->errors)) { //формируем массив данных $data = array('username' => $login, 'password' => $password, 'reg_date' => time()); //$this->model реализует доступ к соответствующей модели $this->model->addUser($data); } } //так как я использую шаблонизатор twig вместо традиционного view, таким образом происходит отправка на рендер в шаблон $template->render(array( 'errors' => $this->errors )); } } В общем как-то так..
В модели лучше реализовать как можно больше бизнес-логики, т.е. не только чтение их из базы, но и все необходимые расчёты, всю логику. Контроллер должен, грубо говоря, просто запрашивать у модели данные, необходимые расчёты, при необходимости передавать ей ввод от пользователя, передавать в представления полученные у модели результаты. Но не должен содержать сам никакую другую логику. таким образом, вы всегда знаете, где искать, к примеру, ошибку. Или что расширять, чтоб добавить функционал.
Сурикат рекомендует не делать MVC самоцелью и бескомпромиссной догмой. Далее - "модель" это не набор методов, получающих данные из БД и файликов. Модель - это и есть сами данные, ребят. Мыслим в контексте информационного потока: 1) Модель - способ внутренней организации и хранения информации. Есть у нас пачка информации, мы можем ее держать в БД, в XML, в JSON, в текстовичке со своей собственной странной разметкой, в шаред-мемори, и, даже в облигациях газпрома. В любом случае данные будут одни и те же. НО, механизмы хранения и способы организации будут сильно отличаться. Это и есть "определиться с моделью". 2) Контроллер - средства обработки информации, шлюз между моделью и вьюхой. Работающий в обе стороны, да. Берет у модели, жует, отдает вьюхе. Потом берет у вьюхи, жует, отдает модели. 3) Вьюха - способ внешней организации и представления информации, ее выдачи и ввода. То есть модель - то, как видит данные нашего проекта машина, вью - как видят ее со стороны. Контроллер - как первое превращается во второе и наоборот. Просто добавьте слово "данных" в каждый из трех пунктов,и все сразу станет прозрачным : 1) Модель данных. 2) Контроллер/обработчик данных. 3) Представление/выдача данных. В данном концепте, к слову, вьюха - не всегда страничка браузера или форма. Вьюхой так же является какой-нибудь API, плюющийся JSON'ами во всех, кто к нему обращается. Пропорции количества моделей-вьюх-контроллеров не должны быть 1:1:1. На весь проект может быть, грубо, 100 контроллеров, 30 вьюх и одна-единственная модель. То есть MVC - это не про резать все на тортики по 3 куска каждый. Это про соблюдать логику в архитектуре. Далее, у людей случается приступ паники, когда они понимают, что НЕ МОГУТ ОТДЕЛИТЬ ПРЕДСТАВЛЕНИЕ ОТ ЛОГИКИ!!111слезы!11БОЛЬ!!11111один!!111страдания11!!!!!Гнев1111разраз Но это не нужно делать любой ценой. Если у вас во вьюхе есть цикл(!!!!боль!!11сжечь!!11слезы!1!!), в котором вы генерите табличку(!!!еретик!1111сжечь!!!!), не спешите вскрывать себе вены - вы не нарушили закон, не опозорили свою честь, не стали причиной катаклизмов, радикальные программисты ислама не объявят вам DDOS-джихад. Все нормально. Вы делаете архитектуру своего проекта, а не она вас. Если в вашем случае требуется такой подход - вперед. З.Ы. Про будущие поколения программистов, которым будет легче понять ваш код, конечно интересно и тешит самолюбие, но открою вам страшную тайну... На ваш код(и на мой тоже, разумеется) всем плевать и никто никогда не будет его ковырять и запиливать, если, конечно, вы не наймете его на работу. Только тссс...
хорошо сказано: и в контексте ООП приложения, данные должны представлять собой максимально простой объект, хранящий необходимый набор свойств. Если для сохранения приходится записывать файл или данные в таблицы, то это может делать функция-хелпер. Мы привыкли к MySQL в вебе, но реляционные базы данных очень и очень далеки от объектов, именно поэтому приходится городить непонятно к чему относящийся огород методов для работы с базой, а-ля ActiveRecord. NoSQL-субд сохраняют и отдают объекты "как есть". Еще есть вариант, "толстая модель", когда класс модели описывает методы для взаимодействия с базой. В этой ситуации надо помнить, что модель не должна изменять данные: только извлекать и сохранять. В модели не должно быть ничего, заточенного под определенный контроллер. Любая модель должна быть совместима с любым контроллером, а вот представления - только с конкретными методами контроллеров.
Кстати да. Вообще, эти вот разделения и так далее нужны не для мифического признания, а просто чтобы через месяц перерыва можно было вернуться и не сломать ногу. Но если вьюха для генерации таблицы может просто выдернуть данные из БД напрямую - нафига городить оверхеды и костыли ради "максимально четкого разделения"? Делать надо не как у соседа, а как в твоем случае вернее. MVC - не закон, а рекомендация. Только и всего.
https://yadi.sk/d/gqhcFS30WCCyF Вот такое для примера накрутил, мини MVC главные действия это регистрация и авторизация пользователя, скажите, правильно ли я все сделал? PS из кода убрано все лишнее, нет маршрутизатора в привычном виде один controller - user, он отвечает за работу с пользователями (регистрация, авторизация), для него предусмотрено 2 model, register_model и login_model (при этом НЕТ user_model, ну а для чего?), ну и куча view под соответствующее происшествие.
Тогда же получится, что всё интересное перенесётся в контроллер, и он станет толстым и уродливым... http://yii.kz/mvc-tolstaya-model-tonkiy-kontroller. Я стараюсь (когда не лень), чтоб у меня в конроллере вообще не было больших функций, и они состояли только из обращения к функциям модели и передачи результатов работы вьюхе
верно. Статья годная, идея - тоже. Опять же одна из предпосылок - сложная реляционная структура из множества таблиц, для хранения в общем-то плоских объектов. Однако в этом случае логика оказывается именно в контроллерах (как и должно быть по первородной MVC), а модель можно заюзать (гипотетически) в других приложениях. Дело в том, что чужие контроллеры никому не нужны, а чужая модель может пригодиться - именно как данные, а логика по обработке данных уже своя. с этим я не соглашусь. Модель самолета - это не самолет, и модель на подиуме - это не человек в жизни. Модель только демонстрирует, чтО есть и как оно выглядит. Она ничего не делает, ну это ИМХО, толстую модель умные дядьки придумали, но запихнуть всю в конце концов ПРОГРАММУ в один компонент и называть это MVC как-то не честно.
Что????? Какой еще оверхед? Логика должна быть отделена от представления. Никаких запросов из представления. Не хочешь использовать MVC не надо. Путать людей то же не надо.
Не, плодить целый класс ради функции login я бы не стал. К тому же, модель, по идее, не должна взаимодействовать с $_POST напрямую. Как бы я сам реализовал - надо подумать. Но у меня бы, скорее всего, был класс User_Model, отвечающий за регистрацию пользователя, ну и выполняющий ещё какие-нибудь функции, которые мне от него нужны. Может над ним ещё один класс Authorization_Provider, который бы занимался непосредственно проблемами авторизации
Тут в укороченном виде, в полноценном было бы на много больше кода, ну может с login и нет, но вот с регистрацией точно. т.е. я в controller должен вытащить значения из $_POST (прогнать через trim и т.п.) и передать их в model?
Не нужно возводить в абсолют это разеделение. Логика представления может и должна быть в представлении. Логика модели может и должна быть в модели. Толстая модель, тонкий контроллер или наоборот — зависит от конкретного проекта или задачи в рамках проекта, единственно верного выбора между этими вариантами не существует. Абстрагируйтесь от Postов. Задача модели — отдать данные по запросу контроллера. Задача контроллера — запросить нужные данные у модели и передать результат их обработки во вьюху. Первый серьёзный проект на Yii/ZF/Symphony расставит всё в голове на свои места. Прикладные вещи сложно объяснять на пальцах.
Ну какие еще догматы. ТС спрашивает как правильно реализовать MVC вы же вместо того что бы направить советуете черт знает что. И еще какой то оверхед приплели, он же помешен на оптимизации не травмируйте человека. Все верно. Как писать не правильно он и без нас разберется.
Контроллер служит как бы диспетчером в приложении. Говоря кому что делать, генерирует события для листнеров, манипулирует контейнером обратной зависимости. Модель представляет слой абстракции над данными. Которыми (данными) могут пользоваться разнообразные модули, слушатели и сам контроллер. Вид - это только шаблоны, никакой сложной логики. Это только обертка, куда вставляются данные чтобы их показать пользователю. И вот например псевдо-код авторизации: - Пользователь запрашивает страницу на сайте по определенному адресу - Апач (ну или что угодно) запускает наш контроллер - Контроллер спрашивает у валидаторов, нормально ли введены данные от пользователя и если да, продолжаем - Контроллер спрашивает у модели "Пользователь", есть ли такой пользователь в БД и если да, продолжаем - Контроллер выстреливает событие "Пользователь заходит", на которое откликаются соответствующие листнеры типо логгера входа, модуля, который выдает пользователю всякие нотификации и тп - Контроллер просит ВИД отрендерить (вставить данные в шаблон так сказать шаблон который надо показать (при удачной регистрации шаблон страницы, а при неудачной, - форму логина с ошибками) - Контроллер возвращает пользователю ответ (в виде отрендереного html)
Столько приведено терминов MVC (я надеюсь вы хоть не сами их писали, а откуда то копировали), но оно не вносит ясность, все это вода, тут как говориться лучше один раз увидеть, чем 100 раз услышать, я даже код написал, загрузил на сервер, может лучше было бы отредактировать этот код, так, как должна выглядеть MVC (я как понимаю если там что то и надо делать, так это пару строк перенести) и вопрос будет исчерпан. Да и на будущее, у не знающих как будет выглядеть MVC будет пример в виде живого кода, а не терминология.
валидатор как я понимаю это например прогон через preg_match, а так же проверка допустим длинны (min/max), где все эти действия происходят на месте, в Контроллере или в Модели? И где происходит вытаскивание данных из $_POST в переменные (массив) для дальнейшей работы в Контроллере или в Модели?
Очень много зависит от конечной архитектуры и твоего видения структуры. Пойми, MVC — это парадигма, первоначальная идея от которой ты потом оттолкнёшься. Не обязательно всегда строго следовать принципу построения. Существуют уйма приложений у которых своё видение MVC и это абсолютно не мешает им развивать свой проект и работать с комьюнити. Кстати, MVC, MVP, MVVC, MVVM и ещё парочка. тут хорошо написали выше про добавление слова «данные». Если совсем академически подходить к вопросу, то контроллер получает из модели Http данные из $_POST, проводит валидации (хэлпер, модель, отдельные валидаторы. Тоже, кстати, интересный вопрос архитектуры). И скармливает какой-нибудь модели User для добавления данных в базу. Вызываем вьюху для вывода ответа пользователю или редиректим дальше. Модель — это вовсе не обязательно только база данных. База, кэш, сессии — для любого типа данных могут быть свои модели. Точно так же вьюхи — вывод html в браузер, запись на диск/ftp, ajax ответы, api (json, xmlrpc, soap), крон
Так это я и пытаюсь выяснить И что подразумевается под словом "обработка", одно дело вытащить (переписать) интересующие данные из $_POST в собственный массив, при этом по необходимости очистить от тегов и выполнить trim, и совсем другое дело проверять через БД (например есть такой пользователь или нет). т.е. например если у нас идет регистрация пользователя, то это происходит так: Код (PHP): class reg_controller { function index() { $view = new reg_view(); $model = new reg_model(); // модель отвечающая за регистрацию // в ней все методы отвечающие за регистрацию $data = $model->get_data(); // метод находится в model (reg_model) // get_data вытаскивает из $_POST интересующие нас переменные // прогоняет их через strip_tags() и trim() и возвращает в виде массива $result = $model->filter($data); // метод находится в model (reg_model) // filter прогоняет через фильтр данные проверяет, длину и preg_match // возвращает true / false if (!$result) { $view->load_view('failed'); // шаблон с сообщением что данные заполнены не верно return; } $result = $model->db_filter($data); // метод находится в model (reg_model) // db_filter проверяет нет ли БД такого пользователя // возвращает true / false if (!$result) { $view->load_view('failed'); // шаблон с сообщением что данные заполнены не верно return; } $model->add_db($data); // метод находится в model (reg_model) // add_db добавляет в БД нового пользователя $view->load_view('success'); // шаблон с сообщение об успехе return; } } так?