MVC模型,它们用于什么?

时间:2011-11-14 01:22:49

标签: php cakephp cakephp-appmodel

现在是时候了解MVC,这就是我想要做的事情;而且我无法获得模型应该做的事情。根据{{​​3}},一个模型:

  

该模型管理应用程序域的行为和数据,   响应有关其状态的信息请求(通常来自   视图),并响应指令改变状态(通常来自   控制器)。在事件驱动的系统中,模型通知观察者   (通常是视图)当信息发生变化时,他们可以做出反应。

在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 个答案:

答案 0 :(得分:5)

这个“对模型类的空扩展”已经做了很多事情:它连接到数据库并完成检索和保存数据的所有分钟处理。 应该做更多事情,包括持有validation rules,这些都是在您写入数据库时​​强制执行的,before/after filters中所需的任何数据按摩以及任何其他自定义您的应用程序中需要的业务逻辑。模型用于存储您的中央业务数据逻辑,因此任何与表示或输入/输出无关但基本上模拟应用程序核心逻辑的内容。仅仅因为基础知识设置简单并不意味着它们没有更多。

答案 1 :(得分:4)

模型还封装了业务逻辑并处理彼此之间的交互。例如,如果帖子有评论,那就是在模型中处理的内容。您不希望控制器获取Post,然后获取注释并组装它们。这将使得知道模型结构的责任在控制器上,而不属于它。

确实存在许多应用程序,其中模型不包含非常多的逻辑(如果有的话)。仅具有数据字段且没有业务逻辑的模型可以被认为是DTO(数据传输对象)或仅仅是“对象”,因为它不“模拟”任何类型的业务逻辑。这不一定是坏事,这取决于需求。许多应用程序都是简单的数据形式应用程序,不需要任何额外的逻辑。

但是,如果您的应用程序具有的逻辑不仅仅是任何给定表中的数据,那么该逻辑就会出现在模型中。他们不只是对数据建模,而是对域进行建模。实际上,模型不直接具有相同的数据库结构并不罕见。模型是面向对象的,而数据库通常是关系型的。这两个并不总是以同样的方式解决问题。如果您的模型需要精确复制表格,那么您将限制自己从更多面向对象的功能。

简而言之,任何可以解释业务运作的内容都会进入模型。控制器只是事件处理程序,响应用户界面请求。控制器通常是为手头的应用程序定制的,而模型应该可以在多个应用程序中重复使用,因为它们代表了业务逻辑的核心。

答案 2 :(得分:1)

使用你的例子,理想的是瘦控制器和胖模型。这意味着您的代码理想情况下应重构为以下内容:

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()代码移动到你的AppModel中,这样每个模型都会继承它:

class AppModel extends Model {

    function retrieveLatest($limit = 10) {

        $model = $this->alias;

        return $this->find('all', array(
            'limit'=>$limit,
            'order'=>array(
                $model . ".id"=>'DESC'
            )
        );

    }    

}

根据经验,只要您发现自己在控制器中构建查询,请将它们移动到模型中并为其提供描述性名称。