用户
 找回密码
 入住 CI 中国社区
搜索
查看: 3787|回复: 9
收起左侧

[讨论/交流] 如何避免在一次请求中,数据的多次查询?

[复制链接]
发表于 2015-3-18 14:48:12 | 显示全部楼层 |阅读模式
对于同一个数据查询,比如当前登录用户个人信息,有可能会存在一次请求中多个地方都需要,比如控制器中,需要根据用户角色做权限判断,view中需要显示用户信息,model中需要使用这个用户的ID来查询关联数据,类库中要使用这个用户的邮箱来发邮件。

如果每次使用这个用户信息时,都去查库,对性能有比较大的影响,但是要实现一次查询到处可用的话,CI框架本身并没有特别的支持。如果是通过参数传递,比如controller调model的方法时,把用户信息传给model方法,这个函数就会显得很奇怪,通用性降低,不利于后期维护。

大家在项目中是怎么避免重复查询的?求指点。
发表于 2015-3-18 15:26:57 | 显示全部楼层
session或者缓存文件,个人观点
发表于 2015-3-19 09:39:14 | 显示全部楼层
本帖最后由 yuzhigang5460 于 2015-3-19 09:45 编辑

不像你问的问题,或者没看懂你问题的本质。

在一个请求里公用的数据,Controller是入口, 客户端首先会发送一些如查询参数或者post过来的数据,控制器用这些数据做入输入,通过使用model来获得更多的视图数据加载视图。 整个过程中,数据一旦加载后,利用已有的数据可以去加载更多数据。不能说已经查询了一次用户信息,现在要加载该用户发表的帖子,model又去加载一次用户信息和帖子信息,这显然不合理。

在一个Session里公用的数据, 一般会扩展一个Controller, 如:
PHP复制代码
 
class MY_Controller extends CI_Controller {
   
        protected $_data = array();
        protected $_user = array();
        protected $_is_login = false;
        public function __construct()
        {
                parent::__construct();
                $this->_pre_controller();
                $this->_fill_common_data();
        }
        private function _fill_common_data()
        {
                $this->_data['is_login'] = $this->_is_login;
                $this->load->model('setting_model', 'setting');
                //……
        }
       
        protected function _pre_controller()
        {
                $this->_user = $this->nsession->userdata('user');
                $this->_is_login = !empty($this->_user);
                if($this->_is_login){
                        $this->_data['user'] = $this->_user;
                }
               //……
        }
 
 
复制代码

每次都可用user信息了,不用自己再多次加载。

另外如楼上所说,可以缓存一些数据库的数据,CI中已经提供了很多缓存驱动,但本质还是那个流程。
发表于 2015-3-19 09:51:12 | 显示全部楼层
又看了一遍的你的问题。细粒度的方法要好于粗粒度的方法,通用性会高,而不是低,当然不能太细,难以维护。这是个权衡。
发表于 2015-3-19 23:18:38 | 显示全部楼层
yuzhigang5460 发表于 2015-3-19 09:39
不像你问的问题,或者没看懂你问题的本质。

在一个请求里公用的数据,Controller是入口, 客户端 ...

你这个也是解决办法哈。。所有的控制器可以继承这个基类。。
调用用户的信息直接 $this->_user 把你的方法改进下 ,属性定义为public , 模版中 model都可以进行调用的!!!!{:soso_e100:}{:soso_e113:}
PHP复制代码
 
<?php
class MY_Controller extends CI_Controller {
 
        public $_data = array();
        public $_user = array();
        public $_is_login = false;
        public function __construct()
        {
                parent::__construct();
                $this->_pre_controller();
                $this->_fill_common_data();
        }
        private function _fill_common_data()
        {
                $this->_data['is_login'] = $this->_is_login;
                $this->load->model('setting_model', 'setting');
                //……
        }
 
        protected function _pre_controller()
        {
                $this->_user = $this->nsession->userdata('user');
                $this->_is_login = !empty($this->_user);
                if($this->_is_login){
                        $this->_data['user'] = $this->_user;
                }
               //……
        }
 
 
复制代码

发表于 2015-3-20 16:11:51 | 显示全部楼层
57sy.com(隐身中 发表于 2015-3-19 23:18
你这个也是解决办法哈。。所有的控制器可以继承这个基类。。
调用用户的信息直接 $this->_user 把你的方 ...

protected修饰符,子类一样可以直接用的。

 楼主| 发表于 2015-3-31 16:18:06 | 显示全部楼层
57sy.com(隐身中 发表于 2015-3-19 23:18
你这个也是解决办法哈。。所有的控制器可以继承这个基类。。
调用用户的信息直接 $this->_user 把你的方 ...

如果我调用了library,也需要这个用户的信息,那么是在library里自己再取一次还是在函数上添加用户信息的参数,由controller传进去?
发表于 2015-3-31 17:22:34 | 显示全部楼层
baiyuxiong 发表于 2015-3-31 16:18
如果我调用了library,也需要这个用户的信息,那么是在library里自己再取一次还是在函数上添加用户信息的 ...

你在library里面完全可以获取到
发表于 2015-3-31 17:23:16 | 显示全部楼层
baiyuxiong 发表于 2015-3-31 16:18
如果我调用了library,也需要这个用户的信息,那么是在library里自己再取一次还是在函数上添加用户信息的 ...

library 一般只是功能的实现, 一般不在里面进行其他的判断的
发表于 2015-3-31 17:33:52 | 显示全部楼层
baiyuxiong 发表于 2015-3-31 16:18
如果我调用了library,也需要这个用户的信息,那么是在library里自己再取一次还是在函数上添加用户信息的 ...

controller传过去。

本版积分规则