Модели MVC, для чего они?
Пришло время понять MVC, вот что я пытаюсь сделать; и у меня проблемы с получением того, что должна делать модель. Согласно Википедии, модель:
Модель управляет поведением и данными домена приложения, отвечает на запросы информации о его состоянии (обычно из представления) и отвечает на инструкции по изменению состояния (обычно от контроллера). В управляемых событиями системах модель уведомляет наблюдателей (обычно просмотров), когда информация изменяется, чтобы они могли реагировать.
А в CakePHP вы предположительно создали модель очень простым способом:
<?php
class Posts extends AppModel {
var $name = 'Posts';
}
?>
Так, если бы я хотел, например, последние 10 сообщений в моей базе данных, я бы создал контроллер, который бы выглядел примерно так:
<?php
class PostsController {
function retrieve_latest($number = 10) {
$posts = $this->Users->find(array(
'fields' => '*',
'order' => 'posts.post_id DESC',
'limit' => $number,
'page' => '1',
'conditions' => array('posts.post_display == 1')
));
$this->set('posts', $posts);
}
}
?>
И этот парень передаст переменную с именем posts
на мой взгляд, что бы сделать это соответственно. Дело в том, разве моя модель не должна делать что-то еще?, потому что если она настолько проста, то для пользовательских моделей вообще не будет смысла, я имею в виду, это просто пустое расширение класса модели.
3 ответа
Это "пустое расширение к классу модели" уже делает много вещей: оно подключается к базе данных и выполняет всю минутную обработку извлечения и сохранения данных. Тем не менее, он должен делать намного больше, в том числе содержать правила проверки, которые применяются каждый раз, когда вы пишете в базу данных, любые массивы данных, необходимые в фильтрах до / после, и любую другую настраиваемую бизнес-логику, необходимую в вашем приложении. Модели предназначены для хранения вашей центральной логики бизнес-данных, поэтому все, что не связано с представлением или вводом / выводом, но по сути моделирует основную логику вашего приложения. То, что основы просты в настройке, не означает, что их больше нет.
Модели также инкапсулируют бизнес-логику и управляют взаимодействиями друг с другом. Например, если сообщение имеет комментарии, это то, что будет обрабатываться в модели. Вы не хотели бы, чтобы контроллер извлекал сообщение, а затем извлекал комментарии и собирал их. Это возложило бы ответственность за знание структуры модели на контроллере, где он не принадлежит.
Действительно, существует много приложений, в которых модели не содержат много логики, если вообще вообще есть. Модель только с полями данных и без бизнес-логики может рассматриваться как DTO (объект передачи данных) или просто как "объект", поскольку она не "моделирует" какую-либо бизнес-логику. Это не обязательно плохо, это зависит от потребностей. Многие приложения являются простыми приложениями для работы с данными и не нуждаются в дополнительной логике.
Но если ваше приложение имеет больше логики, чем просто данные, содержащиеся в любой заданной таблице, эта логика используется в моделях. Они не просто моделируют данные, они моделируют домен. На самом деле, модели нередко не имеют одинаковую структуру базы данных. Модели являются объектно-ориентированными, тогда как базы данных гораздо чаще являются реляционными. Эти двое не всегда решают проблемы одинаково. Если вашим моделям нужно точно копировать таблицы, вы ограничиваете себя в использовании более объектно-ориентированных возможностей.
Короче говоря, все, что объясняет, что делает бизнес, входит в модели. Контроллеры - это просто обработчики событий, отвечающие на запросы интерфейса пользователя. Контроллеры обычно настраиваются для конкретного приложения, в то время как модели следует повторно использовать в нескольких приложениях, поскольку они представляют собой ядро бизнес-логики.
Чтобы использовать ваш пример, идеальным вариантом являются тонкие контроллеры и толстые модели. Это означает, что ваш код в идеале должен быть изменен на следующее:
class Post extends AppModel {
var $name = 'Post';
function retrieveLatest($limit = 10) {
return $this->find('all', array(
'order'=>'Post.id'=>'DESC',
'limit'=>$limit
);
}
}
class PostsController extends AppController {
function retrieve_latest($limit) {
$posts = $this->Post->retrieveLatest($limit);
$this->set(compact('posts'));
}
}
Ваш контроллер не должен беспокоиться о сложных деталях того, что необходимо для получения самой последней бизнес-логики, которая идет в модели, близко к данным. Еще одним преимуществом является то, что вы также можете получить последние сообщения из любой связанной модели:
$posts = $this->User->Post->retrieveLatest();
Вы могли бы даже пойти еще дальше и переместить код retrieveLatest() в свою модель приложений, чтобы каждая модель унаследовала его:
class AppModel extends Model {
function retrieveLatest($limit = 10) {
$model = $this->alias;
return $this->find('all', array(
'limit'=>$limit,
'order'=>array(
$model . ".id"=>'DESC'
)
);
}
}
Как правило, каждый раз, когда вы обнаруживаете, что строите запросы в своих контроллерах, перемещайте их в модель и дайте им описательное имя.