Принципы PHP MVC - PullRequest
       9

Принципы PHP MVC

3 голосов
/ 20 ноября 2011

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

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

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

Файл контроллера

function list() {
    $cars = $this->model->get_all();
    $this->view->add($cars);
    $this->view->render('cars-list');
}

Файл модели

function get_all() {
    // Use a database interaction class that I've written 
    $cars = Database::select();

    return $cars;
}

Теперь, если у машины есть поле "status", которое хранится в базе данных как целое число, и я хочу изменить его на строку, где это должно быть сделано?Зацикливание массива результатов SQL в методе get_all () в модели?

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

$validator = new Validator();    
$validator->check('field_name', 'required');

Если проверка не пройдена, он добавляет сообщение об ошибке в массив в Validator.Этот массив сообщений об ошибках затем будет передан в представление.Должно ли использование моего класса валидатора идти в модели или контроллере?

Заранее благодарим за любую помощь, которую может предложить каждый.Если вам известны ссылки на простой пример MVC / приложение с открытым исходным кодом, которое имеет дело с базовым CRUD, они будут очень благодарны.

Ответы [ 4 ]

4 голосов
/ 20 ноября 2011

Общее распределение обязанностей в MVC обычно выглядит следующим образом:

  • Модель: бизнес логика. Многие люди думают, что модель - это просто интерфейс с базой данных, но это неверно. Модели в вашей системе должны описывать все объекты в вашей системе, как они себя ведут и как они взаимодействуют. Доступ к данным - лишь малая часть этого (и, возможно, его даже следует разделить на собственный уровень доступа к данным, отдельный от модели, представления или контроллера). Например, в приложении для ведения блога блог будет иметь коллекцию постов, и каждая запись может иметь (в зависимости от функций, которые реализует приложение для блогов) коллекцию комментариев. Это будет означать реализацию класса блога, класса поста и класса комментариев. Если вы решите удалить сообщение, оно несет ответственность за то, чтобы оно не оставляло никаких лишних комментариев. Вы могли бы сделать это, имея метод в классе записей для удаления сообщения и аналогичный метод в классе комментариев. Когда сообщение получает сообщение об удалении, оно как часть процесса удаления отправляет сообщение об удалении всем комментариям, связанным с удаляемым сообщением.
  • Вид: логика представления. Представление - это в основном веб-страница, RSS-канал, файл CSV, фактически любые данные, которые ваше приложение может вывести конечному пользователю. Он должен просто отображать переменные, которые были ему присвоены. (Можно реализовать некоторую логику в представлении, если оно связано с выводом данных. Представления не должны быть полностью тупыми)
  • Контроллер: клей логики. Контроллер в основном выполняет две задачи: 1) берет данные из модели, внедряет их в представление и представляет их пользователю. 2) Получите данные от пользователя, отправьте их соответствующей модели для обработки и представьте результаты пользователю. Это означает, что контроллер должен содержать очень мало кода, всего лишь то, что необходимо для достижения двух целей, перечисленных выше.

Как я уже упоминал, многие думают, что модель - это нечто большее, чем уровень доступа к данным. Обычно вы можете сказать, когда люди следовали этой философии дизайна, потому что в результате получаются модели, которые мало что делают, и контроллеры, которые делают слишком много (так называемый антишаблон Fat Controller). Проблема с этим подходом состоит в том, что если вы хотите повторно использовать части вашей кодовой базы в каком-либо другом проекте, то вы не можете перенести модель в новый проект, не взяв вместе с ним большой кусок контроллера. Контроллеры, как правило, считаются специфичными для приложения и поэтому не подлежат повторному использованию. Модели, с другой стороны, включают сущности в ваше приложение, и у вас может быть несколько приложений, требующих использования сущностей одного типа (программное обеспечение для ведения блогов, витрины электронной коммерции и доски объявлений - все очень разные приложения, но все они нуждаются в реализовать пользователей).

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

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

Как правило, я реализую уровень проверки в моих моделях, как правило, довольно базовые проверки работоспособности (например, требующие, чтобы целые числа были фактически значениями типа и т. Д.), И реализую отдельный набор классов для полной проверки ввода. Я вызову классы проверки в моем контроллере, и если проверка не пройдет там, я представлю результаты представлению. Если это удается, то данные отправляются в соответствующую модель для обработки. Я полагаю, вы можете назвать валидацию «служебной логикой», то, что вам нужно делать регулярно, которую вы не можете привязать ни к одной модели, представлению или контроллеру.

4 голосов
/ 20 ноября 2011

Я настоятельно рекомендую вам взглянуть на "Шаблоны архитектуры корпоративных приложений" Martin Fowler . В нем есть хорошее объяснение того, каково каждое из разделений обязанностей для каждого из компонентов MVC (плюс лот других полезных шаблонов).

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

Короче говоря, вы правильно настроили структуру. Ваш контроллер сообщает модели о том, что произошло какое-то событие, модель реагирует на это событие, затем представление использует модель для представления состояния системы конечному пользователю. Проверка должна выполняться в вашей Модели, поскольку она отвечает за поддержание правильного состояния системы. У вас также может быть некоторая проверка на стороне клиента, которая строго предназначена для уменьшения сетевого трафика и обеспечения более приятного интерфейса для пользователя.

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

Еще одна книга, которую я бы порекомендовал, - Эрик Эванс, «Управление на основе доменов: решение сложных задач в программном обеспечении». Фокус с DDD заключается в том, что «основное внимание должно уделяться домену и доменной логике».

1 голос
/ 20 ноября 2011

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

1 голос
/ 20 ноября 2011

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

Итак, я бы использовал метод getStatus () в классе Car, который вы бы вызывали ПОСЛЕ getAll () всякий раз, когда вам это нужно. Вы будете делегировать актерский состав на уровне предмета. Лучше не давать остальной части вашего приложения знать, что у вас есть целое число на самом низком уровне. Разоблачить строку из машины и жить с ней в остальной части вашего приложения.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...