MVC中Controller和Model的区别

Posted

技术标签:

【中文标题】MVC中Controller和Model的区别【英文标题】:Difference between Controller and Model in MVC 【发布时间】:2011-09-19 09:17:20 【问题描述】:

我对 MVC 框架(codeIgniter)中的控制器和模型有点困惑。我很清楚控制器方法调用视图和模型方法与数据库交互。 但是,我对以下类型的方法有点困惑,它们由控制器中的方法调用。

hash_password              //returns hash password. 
valid_email               //validates email format and return true or false
is_logged                //check if session has a variable, returns true or false
generate_random_string  //generates and hashes a random string

它们应该放在控制器还是模型中?

目前我将上述所有功能都放在一个控制器中。对吗?

【问题讨论】:

我认为密码应该如何散列应该由模型处理,因为模型知道密码将如何存储。也许最后一个应该在帮助文件中。其他的不清楚。 可以说他们都可以进入模型,返回真/数据或假,并允许您的控制器根据需要重定向,假装“瘦控制器,胖模型”。出于个人喜好,我倾向于选择modelmodel/helper(base) controllerhelper 【参考方案1】:

通常控制器用于确定如何处理发出的 http 请求..

创建一些直接响应http请求的函数没有错。

但如果它与数据库有关,最好将这些函数放在模型中,并从控制器中调用它们。

【讨论】:

【参考方案2】:

我认为is_logged 应该放在User 的模型中。请注意,User 可能是您案例中的客户,也可能是您为建模服务用户而创建的任何类。

valid_emailgenerate_random_string 或多或少是实用函数,您可以将它们放在UtilityUtilities 模型中,这样它们就可以在您的应用程序中的各种控制器中重复使用。

hash_password 可以放置在User 模型或Utility 模型中。我更想把它放在Utility 模型中,因为它是一个散列函数,用户不关心什么。但是,我可以想象否则可能会有争论。

以下 SO 问题(尽管针对不同的框架)也可以作为经验法则:

Where to put custom functions in Zend Framework 1.10

【讨论】:

【参考方案3】:

控制器应该结合视图和模型,所以每个验证都应该放在模型中 这是我来自 kohana 的例子

控制器

<?php
/**
 * User Controller
 */
class Controller_Admin_User extends Controller_Admin_Template 

    public function action_index()
    
        $this->template->body = View::factory('admin/user/index')
                ->set('i', 0)
                ->bind('users', $users)
                ->bind('groups', $groups)
                ->bind('id_user_group', $id_user_group);

        $model_user = new Model_Admin_User;
        $users = $model_user->get_users(Arr::get($_GET, 'sort'), Arr::get($_GET, 'order'));

        $model_usergroup = new Model_Admin_Usergroup;
        $groups = $model_usergroup->get_user_group();
    

    public function action_add()
    
        $this->template->body = View::factory('admin/user/form_add')
                ->bind('error', $error)
                ->bind('groups', $groups)
                ->bind('post', $post);

        $model_usergroup = new Model_Admin_Usergroup;
        $groups = $model_usergroup->get_user_group();

        if($_POST)
        
            $model_user = new Model_Admin_User;
            if($model_user->save($_POST) == false)
            
                $error = $model_user->error;
                $post = $_POST;
            
            else
            
                $this->request->redirect('admin/user');
            
        
    

型号

class Model_Back_User extends Model 

    private $qb;

    public $aliases = array(
        'id'=> 'id_user'
    );

    public $error = array(
        'name'          => null,
        'surname'       => null,
        'login'         => null,
        'password'      => null,
        'id_user_group' => null,
        'old_password'  => null,
        'new_password'  => null,
        'confirm'       => null,
        'email'         => null,
        'phone'         => null,
    );

    private $rules = array(
        'name'          => array('not_empty' => null, 'alpha' => null),
        'surname'       => array('not_empty' => null, 'alpha' => null),
        'login'         => array('not_empty' => null),
        'password'      => array('not_empty' => null),
        'id_user_group' => array('not_empty' => null),
        'email'         => array('not_empty' => null, 'email' => null),
        'phone'         => array('not_empty' => null),
        'old_password'  => array('not_empty' => null),
        'new_password'  => array('not_empty' => null),
        'confirm'       => array('matches'   => array('new_password'))
    );

    public function __construct()
    
        $this->qb = new Querybuilder;
        //parent::__construct();
    

    public function change_password($data)
           
        $validate = Validate::factory($data)
            ->filter(true,              'trim')
            ->rules('old_password',     $this->rules['old_password'])
            ->rules('new_password',     $this->rules['new_password'])
            ->rules('confirm',          $this->rules['confirm'])
            ->callback('old_password',  array($this, 'password_exists'), array('id_user'=> $data['id_user']));

        if($validate->check() == false)
        
            $this->error = array_merge($this->error, $validate->errors('user'));
            return false;
        

        $u = Session::instance()->get('user');
        $this->edit(array('password'=> $this->password($data['new_password'])), array('id_user'=> $u['id_user']));
        return true;
    

    public function password_exists(Validate $valid, $field, $param)
    
        if($this->user_exists(array('password'=> $this->password($valid[$field]), 'id_user'=> $param['id_user'])) == false)
        
            $valid->error($field, 'old password is incorrect', array($valid[$field]));
        
    

    public function save($data)
    
        $validate = Validate::factory($data)
            ->filter(true, 'trim')
            ->rules('name', $this->rules['name'])
            ->rules('surname', $this->rules['surname'])
            ->rules('user_group_id', $this->rules['id_user_group'])
            ->rules('email', $this->rules['email'])
            ->rules('phone', $this->rules['phone']);

        $edit = false;
        if(isset($data['id_user']) AND Validate::not_empty($data['id_user']))
        
            $edit = true;
        
        else
        
            $validate->rules('login', $this->rules['login'])
                    ->rules('password', $this->rules['password']);
        

        if($validate->check() == false)
        
            $this->error = array_merge($this->error, $validate->errors('user'));
            return false;
        

        if($edit == true)
        
            $this->edit(
                array(
                    'name'          => $data['name'],
                    'user_group_id' => $data['user_group_id']
                ),
                array(
                    'id_user'=> $data['id_user']
                )
            );
            return true;
        
        return $this->add(
                    array(
                        'name'          => $data['name'],
                        'login'         => $data['login'],
                        'password'      => $data['password'],
                        'user_group_id' => $data['user_group_id']
                    )
                );
    

    protected function add($data)
            
        $data['password'] = $this->password($data['password']);

        return $this->_db->query(Database::INSERT, 
            $this->qb->insert('user')->set($data)->build_query()
        );
    

视图不是那么重要,所以我不把它放在这里。

【讨论】:

【参考方案4】:

一般来说 - 模型应该了解它自己的数据。因此,任何纯粹与模型自己的数据相关的东西 - 都应该放在模型中。

例如 hash_password 和 email-validation 方法 - 模型应该知道如何验证或更新它自己的数据字段,所以这些应该进入模型。

但是控制器应该知道如何正确地引导用户操作并为视图加载正确的模型等。

EG 与会话相关的方法应该放在控制器中,因为会话用于存储用户的状态(基于过去的操作)。

“生成随机字符串”方法非常模糊,可能到处都在使用。我会把它放在一个单独的库中,可能包含在模型/控制器中。

【讨论】:

【参考方案5】:

我已经使用 Codeigniter 很长时间了,就放置而言,我会对你的函数执行以下操作:

hash_password              //returns hash password. 

我会将密码哈希器之类的东西放在库或帮助文件中,这样我就可以从我的控制器中调用它:

// pretend library I'd make for tasks like hashing etc
$this->load->library('passwords');
// transform posted password into it's hashed version   
$password = $this->password_library->hash_password($this->input->post('password'));

我假设您想在该示例中对密码进行哈希/加盐并将其存储在您的数据库中

valid_email               //validates email format and return true or false

这已经在 form_validation 中了,所以...

is_logged                //check if session has a variable, returns true or false

这也应该连接到身份验证库

generate_random_string  //generates and hashes a random string

同样,这将来自库或助手。

那么你什么时候使用模型?

我,我在数据库中使用专门用于输入/输出的模型。我所有的查询都在那里。我通常让模型的函数返回数据对象,这样我就可以在视图中循环它们。

控制器从您的模型中调用您的数据,然后将所有内容转储到您的视图中。外部功能总是进入库和助手。我喜欢做“MY_library”并扩展 Codeigniter 自己的东西——尤其是表单和 html 助手等。

【讨论】:

以上是关于MVC中Controller和Model的区别的主要内容,如果未能解决你的问题,请参考以下文章

MVC与MVVM区别?

MVC与MVVM区别?

extjs mvc和mvvm哪个好

Android MVC模式和MVP模式的区别

MVC和MVVM的区别 & vue的虚拟DOM的理解

MVC和MVP到底有什么区别呢?