Где правильнее проверять пользовательские данные? В контроллере или модели?

Пишу свой велосипед (на вопрос зачем отвечать отказываюсь). Хочется сделать максимально "правильно". Сейчас леплю валидацию форм, вот и возник такой вопрос - где грамотрее ее разместить? Модель, контроллер или вообще отдельный класс? Если отдельный - то опять же, где его использовать?
  • Вопрос задан
  • 4727 просмотров
Решения вопроса 1
IvanCher
@IvanCher
Мысли шире
За работу с данными должна отвечать модель. Именно модель должна знать какие данные допустимы, а какие нет, потому что на ней лежит функция обработки/записи этих самых данных.
У контролера цель - обрабатывать пользовательские запросы и решать, как на них ответить.
Иными словами, вы принимаете данные с формы контролером и говорите модели сказать валидные ли данные пришли. Модель отвечает контролеру, контролер принимает решение, как на это ответить пользователю (ошибкой, каким-то конкретным представлением и т.п.).
UPDATE
MVC советую всем прочесть, прежде, чем давать странные советы. Особенно внимательно прочесть "Наиболее частые ошибки", как раз говориться, что делать из контролера Толстый Тупой Уродливый Контролер - не правильно по определению шаблона. Можно спорить сколько угодно, но об этом прямо многие авторитеты. Другое мнение сформировано отсутствием глубокого понимания MVC и малым опытом на крупных проектах.
Ответ написан
Пригласить эксперта
Ответы на вопрос 9
Мне кажется лучше создать отдельные классы для валидации данных(Helper...) и вызывать их в контроллере. По сути такие классы также являются моделями с какой-то стороны. Контроллер не должен сам работать с данными.
Ответ написан
Комментировать
FanatPHP
@FanatPHP
Чебуратор тега РНР
Ларавель предлагает проверять прямо в роутере
Что снова подтверждает мою мысль о том, что раут в Ларавели - это тот самый тонкий контроллер, о котором так много говорили большевики, конроллер - это модель, а модель - это тупо драйвер БД (ОРМ), используемый моделью.
Ответ написан
neuotq
@neuotq
Прокрастинация
Контроллер. Хотя конечно бывают и модели(тут скорее на более низком уровне) с автоматической проверкой данных, но это все же контроллер.
UPD
Вот хороший пример:
Валидация никнейма, только латиница.
Проверка на латиницу - в контроллере.
Проверка на дубль с уже существующим - в модели, часть бизнес логики.
Я считаю что из-за ошибки в вводе(когда ввели кириллицу) зазря загружать модель, который часто монстр, не нужно. Быстро и просто отсечь в контроллере.
Иван прав в том что структурно это все же модель, но физически в проектах ситуации разные. Я уточню что я больше говорил про отсечение стандартных ситуаций, которые от модели практическине зависят. В целям производительности их можно и выносит в контроллер, опять таки скорее как руками(контроллер) взяли посмотрели и увидели это ключ до вставки в замочну скважину(модель и основная бизнес логика). А ведь глаза в данном случае смотрят на модель(замочная скважина) и выходит они часть модели.
Так что в целом на 100% прав Иван, при проектировании нужно понимать что любая валидация это часть модели, просто иногда кажется что это часть контроллера или даже представления, но то всего лишь интерфейсы оьбращения через контроллер к модели.
Так что валидация это: получили данные, контроллер знает к какой модели их давать, у модели должен быть инструмент валидации, далее он возвращает результат ну и мы решаем что и как.
Я просто поспешил сказав что валидация часть контроллера, но то что она вызывается в контроллере не отменяет того факта что это часть модели.
Ответ написан
Комментировать
@vedmaka
Встречал такой вариант: модель содержит правила валидации, отдельный класс по ним проверяет юзерский данные в контроллере.
Ответ написан
@kejinzo
Java Developer
Да, в контроллере с помощью модели.
Ответ написан
Комментировать
MegaMufa
@MegaMufa
Я считаю, что "толстая модель, тонкий контроллер" - это самый подходящий вариант.
Вся логика приложения должна содержаться в моделях. Модель - это не просто сущности из бд, это еще и инкапсулированая логика ее обработки. А контроллер должен говорить модели, что делать и рендерить вьюхи.

Например этот кусок кода неправильный:
class MyController
{
    public function myAction()
    {
        $user = new User();
        $user->load($_POST);
        if ($user->valiadate()) {
            $user->saveToDatabase();
        } else {
            throw new Exception("...");
        }
    }
}

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

Правильно быдет так: в модели определеить метод, содержащий логику:
class User
{
    public static function create(array $data)
    {
        $record= new static;
        $record->load($data);
        if($record->validate()){
            $record->saveToDatabase();
        } else {
            throw new Exception("...");
        }
        
        return $record;
    }
}


А в контроллере просто дергать его и передавать туда данные:
class MyController
{
    public function myAction()
    {
        $user = User::create($_POST);
    }
}


Таким образом все логика работы модели (в том числе валидация) инкапсулирована снутри класса, и другие классы не знают, как это происходит.

Такой подход облегчает сопровождение кода а так же облегчает написание тестов.
Ответ написан
b0nn1e
@b0nn1e
Alcohol & Ruby on Rails
В Ruby On Rails валидация идет в модели, в контроллере мы пытаемся создать объект и проверяем если проходит валидацию, то все ок одно действие, если не проходит то отдаем ошибки, или рендерим форму с ошибками.
Ответ написан
Комментировать
@Shua_inc Автор вопроса
Не ожидал честно говоря такого эффекта))
Из всего написанного я сделал следующие выводы:
Контроллер должен тупо передавать данные модели. А та уже творит с ними все что заблагорассудится.
Собственно валидатор может быть реализован как метод модели, так и отдельный класс, но вызываться должен именно в модели.
На сколько такой подход оптимален - зависит от конкретного проекта, но он максимально соответствует концепции MVC.
Ответ написан
Интересный вопрос.
В документации CodeIgniter библиотека валидации подключается и используется в контроллере:
<?php

class Form extends CI_Controller {

        public function index()
        {
                $this->load->helper(array('form', 'url'));

                $this->load->library('form_validation');

                if ($this->form_validation->run() == FALSE)
                {
                        $this->load->view('myform');
                }
                else
                {
                        $this->load->view('formsuccess');
                }
        }
}

Документация
Соответственно, я в своих проектах всегда так и делаю...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы