【问题标题】:Object Oriented Approach in Codeigniter ModelCodeigniter 模型中的面向对象方法
【发布时间】:2014-01-16 22:03:39
【问题描述】:

我一直想知道在模型中以 OO 风格编写代码的正确方法是什么。当然,您可以拥有一个从数据库中检索数据然后映射到模型级变量的函数。但是,当您在模型中有其他功能试图从 BD 获取其他数据时,这种方法会变得违反直觉。例如:

class User extends CI_Model {
    $id, $name, $age .... ;

    public function get_user_from_db_with_id($id) {
        ...
        // get data and map to variable. 
    } 

    public function get_all_users() {
    // return all users in db
    }

}

控制器中的某处:

$user = new User();
$ben = $user->get_user_from_db_with_id($id);

// this does not make sense!! 
$all_user = $ben->get_all_users();

有什么想法或意见吗?

提前致谢!

【问题讨论】:

    标签: codeigniter oop model codeigniter-2


    【解决方案1】:

    我不得不做出类似的决定并选择了这个(为了清晰起见)

    class UserModel extends MY_Model 
    {
    
        public $UserID = 0;
        public $CustomerID = null;
        public $FirstName = '';
        public $LastName = '';
        public $EmailAddress = '';
        public $Password = null;
        public $UserGroupID = true;     
    
        function __construct()
        {
            parent::__construct();
        }
    
        private function get($id)
        {
            $row = $this->get($id);
            if ($row !== null)
            {
                $this->dbResultToObject($row, $this);
            }
        }
    
        // Return an array of User objects
        public function get_list($deleted = false, $userIDToInclude = null) 
        {
            $params = array(null, $deleted, $userIDToInclude);
            $query = $this->db->call("spUserGet", $params);
    
            $users = array();
            foreach ($query->result() as $row)
            {
                $user = new UserModel();
                $this->dbResultToObject($row, $user);
                $users[] = $user; 
            }
    
            return $users;        
        }
    
        // Other Methods (Validate, Save etc)
    }
    

    我混合使用公共、受保护和私有属性,以便我编写的反射代码将属性从 DB 结果映射到 DB sproc 调用,然后只包含公共属性并防止发送太多参数.但这已经跑题了,所以我的控制器看起来像:

    class Users extends MY_Controller 
    {
    
        public function __construct()
        {
            parent::__construct();
            $this->load->model('UserModel', 'user');
        }
    
        ....
    
    }
    

    然后可以使用以下方法检索列表

    $users = $this->user->get_list();
    

    还有一条记录

    $user = $this->user->get($userID);
    

    【讨论】:

    • 嘿,太好了。您是否更新了模型代码?比在这里更新。我做过和你一样的事。但如果您已更新,想了解更多功能
    【解决方案2】:

    我非常喜欢根据“角色”而不是资源来考虑设计。所以“用户”将能够获得他们自己的个人资料。但它只会是能够获取所有用户配置文件的“管理员”。

    因此,用户可以做什么 - 获取一条记录 - 和管理员可以做什么 - 获取所有记录 - 之间的区别和重要分离始于为每个控制器设置单独的控制器。用户控制器方法基于验证单个用户并授予他们访问一条记录的权限。 Admin Controller 方法基于验证管理员并授予他们对所有记录的访问权限。即使从 URL 设计的角度来看,这也是有道理的——您希望您的管理区域清楚地分开。

    控制器上的这种分离使一切变得更简单、更容易。当您以资源为导向时,您会不断检查每种方法甚至是您的视图中的凭据。视图应该尽可能简单,而不是“这个人是管理员”吗?当您面向角色时 - 您检查控制器中的凭据 - 然后您的方法、模型和视图适合该“角色”需要完成的任务。

    【讨论】:

    • 我可以看到你的“角色”方法可以节省很多乏味(不断检查凭据)。我将在我的下一个项目中尝试这一点。我想知道您是否为用户和管理对象使用了一个通用的专用控制器类。
    【解决方案3】:

    既然你在考虑面向对象编程,我认为你需要思考:这个类代表什么?

    1. 每个实例意味着一个用户?
    2. 每个实例意味着一个用户数据生成器?

    如果是第一种情况,那么这个类具有 $id、$name、$age 等属性是有意义的。 以下代码有意义

    $user = new User();
    $ben = $user->get_user_from_db_with_id($id);
    

    如果是第二种情况,你的示例中不应该有 $id、$name、$age 之类的属性。

    还有这些代码

    $all_user = $ben->get_all_users();
    

    应该换成这个

    $all_user = $user->get_all_users();
    

    【讨论】:

    • 您好,川浩,谢谢您的回复。我也想过这个。这实际上意味着对于 db 中的每个表,您的代码中需要有两个类:一个用于表示对象,另一个用于检索数据并将数据映射到表示对象的类中,这有点混乱。
    • 此外,您并不总是从数据库中获取表的每一列,这意味着您不必将数据映射到对象表示类中的每个数据字段。