Интересует мнение сообщества по следующему вопросу. Разрабатывается веб-сайт с использованием MVC, интересует вопрос где производить проверку данных пришедших от пользователя на валидность. В модели или в контроллере и конечно объясните своё мнение.
Проводи, где тебе удобнее. Ты программист или копипастер? "Где удобнее" подразумевает, то, что ты не будешь после этого делать больше костылей, где ты будешь смотреть на код и он будет радовать глаз и ты будешь кайфовать, смотря на валидацию.
Валидация это принадлежность модели. Только она знает что ей нужно и в каком виде. Но вызывать валидацию должен тот кто пользуется моделью, т.е. контроллер. Здесь форма выступает простейшей моделью. Вместо нее(или после нее) может быть Domain модель. PHP: <?php class UserController extends Zend_Controller_Action { public formAction() { $frm = new My_Form(); if ($this->getRequest()->isPost()) { if ($frm->isValid($this->getRequest()->getPost()) { } } } } Естественно, если кто-то другой(не контроллер) будет использовать нашу модель, то и он может использовать валидацию модели.
Допустим есть такая ситуация: есть товар соответственно есть его модель которая связана с таблицей характеристик о товаре. К данному товару относится несколько изображений (число не известно) - соответственно имеется другая модель (изображения) которая связана с таблиецей изображений (в ней хранится id товара и id изображения). Сами файлы изображений сохраняются в папке на диске и обзываются id.jpg. Нам нужно проверить правильный ли тип файла загрузил пользователь и все ли обязательные характеристики указал у товара. Получается в модели товара мы устанавливаем правила валидации (обязательно должно быть заполненно название). В модели изображений никаких правил мы не можем указать (ей то побарабану какой файл пришёл) она должна просто вставить запись в таблицу с Id товара и получить Id изображения которое сгенерировалось как autoincrement. Получается проверять тип файла будет контроллер. В итоге имеем два типа валидации (одна в контроллере другая в модели). Не логично бы вынести валидацию в контроллер и не прыгать по между ним и контроллером при написании кода (изменении правил валидации)?
Если MVC правильная, то должна валидировать и приводить в нужный вид данные модель. Это как клиент-сервер, где контроллер - клиент.
[vs] мвц чисто правильно никогда не делают, иначе бред будет, что ты даже любые самые мелкие проверки и действия обязан будешь выносить в модель
Нет одного решения. Обычно проверки размазаны - часть в модели, часть в контроллере. В модели сидят проверки относительно данных самой модели и вызываются они обычно на (условно) onBeforeSave событии. Как правило в фреймворках есть уже готовые решения для создания валидаторов методом описания условий. А вот проверки на связность данных - в контроллер. Например, объект фирмы имеет связь с объектом города - тут никак не запихнуть проверку города в модель. Для себя стараемся придерживаться такого правила - модель не должна ничего знать про другие модели. Т.е. внутри модели не должно быть никаких созданий/вызовов объектов других моделей. Следует это из правила уменьшения сцепок. Но, опять же, это правило, которое можно (и иногда нужно) нарушать, хотя его наличие заставляет обосновывать - действительно ли нужно одной модели лезть в другую или все же можно обойтись. Как правило, условно можно разделить модели на прикладные и самодостаточные. Например, фото - это исключительно прикладная модель, с которой мы можем работать изнутри той модели которой эти картинки нужны. А вот, к примеру, модель города - это уже самодостаточная модель, которая связана с другими - работа с ней должна идти в контроллере. Опять же сложно описать критерии - когда можно, когда нет... все порой на интуиции, которая является следствием опыта. В случае изображений мы поступили так: есть некий класс "коллекция файлов", который по сути является неким датамапером для работы с изображениями. Он умеет по имени модели строить путь и возвращать набор объектов изображений, а так же умеет делать "save" в т.ч. из uploaded фалов. Для каждой модели, которая работает с изображениями есть соответствующая модель картинки (наследованная от общей, конечно) - всякие проверки на форматы, ресайзы и т.д. уже в ней. Т.е. по сути в модели товаров у нас только Toolkit::instance()->getCollection()->uploadFiles("МодельИзображенийДляТоваров"). Колекция же по сути делает для каждого файла new "МодельИзображенийДляТоваров" и потом этому объекту save(), а тот уже на save() делает все, что нужно.
Всем спасибо за обсуждение. Понял для себя что в зависимости от ситуации надо использовать. Хотя так и думал, просто хотелось чтобы валидация проходила в одном месте и не прыгать от файла к файлу. Получается что так может получится только если проводить её в контроллере. Но по логике она должна делаться в модели (примеры из постов это подтверждают) следовательно будем смотреть на ситуацию и делать проверки в зависимости от неё.
если у вас есть/будет пример, где данные модели надо валидировать в контроллере, напишите сюда, пожалуйста.
Ок, договорились. Сейчас пересмотрел ситуация с файлами изображения и понял, что валидацию можно вынести в модель. Следовательно пока такого примера нет. Если появится обязательно напишу. Ну ждём таких примеров от участников обсуждения.
iliavlad у меня данные валидируются в контроллере ибо модель требует корректный данных. Я всегда валидирую данные на входе потому как не хочу чтобы левые данные где-то блуждали еще пока не пройдут валидацию где-то в модели. Смысл? Один хрен контроллер отправляет в другую степь если данные не такие как надо, зачем именно в модели их проверять? Ну может так и надо, но мне удобнее по моему, а "если нет разницы зачем платить больше"?
Костян а контроллеров несколько может быть в разных частях сайта - поэтому удобнее по-моему в модели... в модель отдал данные, и не паришься, валидные они или нет - она "разберется" хотя некоторые моменты допустимо проверять в контроллере
мясо надо) что за модель? что у нее за данные, которые должны быть корректными на входе (даже скорее перед входом)? используется еще где-то? как обойти дублирование кода ("зачем платить больше"), если модель используется еще где-то и данные снова должны быть корректные? менялась ли модель в процессе разработки? если да, как вы отслеживали, что в контроллере и других местах использования модели все данные валидировались? извиняюсь, что много вопросов.
Да ниче - ответ один, как для тебя так и для sylex - я юзаю что-то типа command или вроде точнее reactor, поэтому как таковое понятие контроллера у меня размыто немного и код не дублируется, просто один контроллер обращается как бы к другому... В принципе это уже не совсем контроллер с ваших точек зрения, но кроме как он больше никто делами контроллера не занимается.... От така фигня ))
hardj Все на эксепшенах и все в моделях. Потому что модель используется и внутри других моделей и в кроновских скриптах и в веб-сервисах. А контроллеров там не будет. Так что вот и подумай.
В вашем случае понятно. ПРосто пока не сталкивался с необходимостьюв кроне использовать модели. Да и используя MVC разрабатываю недавно. Поэтому и интересуют фундаментальные вопросы.
hardj пока не привели пример с необходимостью валидации данных в контроллере, можешь валидировать всё в модели)
Проверять ты можешь где угодно. Но метод валидации предоставляет модель. Только она может знать что ей нужно и в каком виде. PHP: <?php class UserController extends Zend_Controller_Action { public function updateAction() { $mdl = new Model(); if (!$mdl->isValid($this->getRequest()->getParams())) { die("Все пропало шеф!"); } } } глупости какие Bingo!
b]Simpliest[/b] По-моему в кроновском скрипте нет ни url ни request, но конечно можно их искуственно создать, если по-другому никак. hardj кстати когда модель приучена к контролеру, только так и остается поступать, чтобы чего-то от нее добиться. Это надо эмулировать запрос, запустить целый паровоз из раутер - диспечер - контролер и заблудиться в нем, чтобы в конце концов прийти в акшен, который только и нужет был. это получается программировать мвц, чтобы повторить ту ошибку, от которой учит мвц. когда модель чистая, всегда остаатся возможность писать код без контролеров и вьюшек. например служебный скрипт такого вида PHP: <?php $model= new Model(); $model->a= $argv[1]; $model->doSomething(); Если в doSomthing() у тебя модель ожидает, что в ней провалидированные контролером данные, считай ты приучил ее к контролеру. А зачем тебе тогда мвц?
кто такое сказал? Это доказано как закон? Или может аксиома? Без всяких упрёков к тебе, но поначитаются авторитетных авторов, которые навяжут вам свое мнение, а потом рассказывают, что да как надо. Всё программирование заканчивается на Макконнелле. Выше уже специализация.
Иногда правильно и в контролере. валидация тоже бывает разной. есть валидация уровня бизнеслогики, есть валидация уровня интерфейса. но это совсем другой случай. например если есть модель, которая делит два числа class DivModel{ fnc div(inx x, int y){ } } если в скрипте то все понятно. если эту же модель использовать через веб-нитерфейс, то появляется дополнительная валидация. валидация у!=0 - это валидация уровня бизнеслогики и она правильно делаться внутри модели, а не в каком-то контролере. А валидацию x и y - это два чиста, а не две строки 'qwerty' можно/нужно делать внутри контролера, потому что это не относится к бизнеслогике. и все везде всегда на исключениях
URI - это адрес ресурса с параметрами и ничего более. чем отличается GET /localhost/cli.php?param=1 от php.exe D:\www\cli.php param=1 Да ничем. Единственное что PHP для тебя распарсит параметры и создаст $_GET/$_POST/$_COOKIE Для CLI у тебя эти параметры будут в $argv, а в $argc будет их число. Все. Слушай, завязывай а? Я терпеть не могу глупости. Модель вообще ни к чему не приучена. Она получает данные и может с ними что-то сделать. PHP: <?php $mdl = new Model(); $mdl->isValid($argv); $mdl->isValid($_POST); $mdl->isValid(array('param' =>1)); Но о других моделях она знать ничего не знает и не должна. Поэтому этот паровоз как ты изволил выразится вызван одним простым принципом DRY - don't repeat yourself Дабы не страдать маразмом и не прописывать связи и бизнеслогику отдельно для CLI версии, пишется вот такой раннер и используется уже готовый код.
Это логика сказала. Вы ее не слушаете? Кроме меня самого никто не знает люблю я картошку-фри или бешбармак. Поэтому и говорить нравится/ненравится valid/not-valid - мне, а не тебе. Ты можешь у меня спросить, но не более того. Потому что завтра вкусы у меня изменятся, а ты по-прежнему будешь уверен что бешбармак и блондинки это то, что мне нужно. Ты заблуждаешься. Знаешь в чем твоя проблема? В том, что ты наивно полагаешь, что мне можно навязать мнение одним лишь авторитетом. Я не читал ни одной книги по программированию за последние 17 лет, но с логикой я дружу. И мне будет плевать на Фаулера, Макконела и других, если они начнут нести чушь. И не надо говорить глупости, я этого не люблю.