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

[修补 Patch] 突破在使用AR过程中所遇到的一个瓶颈!

[复制链接]
发表于 2012-3-19 12:16:16 | 显示全部楼层 |阅读模式
本帖最后由 CM帮主 于 2012-3-19 14:06 编辑

对于在使用AR过程中所遇到的一个瓶颈!

  个人比较喜欢它使用CI,而在开发过程中经常会使用到里面的AR来生成查询!
但是最让我苦恼的是,在使用过程中,在生成部分语句的时候总是难以实现!
就比如:(注:这里字段前的表名是特意加上的,为了下面说明问题!)

SQL复制代码
SELECT * FROM USER WHERE (USER.name='CM帮主' AND USER.note='CM帮主描述') OR (USER.name='CMivan' AND USER.note='CMivan描述');
 
复制代码


因此我尝试了这样写:
$this->db->from('user');
$this->db->where('user.name','CM帮主');
$this->db->where('user.note','CM帮主描述');
$this->db->or_where('user.name','CMivan描述');
$this->db->where('user.note','CMivan描述');

结果返回的查询语句是这样的:
SQL复制代码
 
SELECT * FROM (`user`) WHERE `user`.`name` = 'CM帮主' AND `user`.`note` = 'CM帮主描述' OR `user`.`name` = 'CMivan' AND `user`.`note` = 'CMivan描述';
 
复制代码


唉!完全不是我要的东西!在接下来的一段时间,在网上没有找到生成我需要的这种写法!怎么办呢!?~?
好!突然想起AR的一个自带的一个写法,如下
$this->db->from("user");
$this->db->where("(user.name='CM帮主' and user.note='CM帮主描述') or (user.name='CMivan' and user.note='CMivan描述')");

结果返回的查询语句是这样的:
SQL复制代码
 
SELECT * FROM (`user`) WHERE (USER.name='CM帮主' AND USER.note='CM帮主描述') OR (USER.name='CMivan' AND USER.note='CMivan描述');
 
复制代码


来到这里,我是相当的开心啊!这正是我所需要的哈,没想到AR已经想到了会出现这种特殊情况,为我们自由发挥留下了一扇门啊!
这真的可以说是相当开心!,觉得这样AR有 $this->db->where('{sql}') 这种写法 就可以帮我解决很大一部分的查询难题了!






好!又过了一段时间,因为开发需要,我要对表加上前缀!

因此我修改了配置文件如下:
$db['default']['dbprefix'] = 'exp_';


新问题就来了,原来的语句查询的结果变成了这样:
SQL复制代码
 
SELECT * FROM (`exp_user`) WHERE (USER.name='CM帮主' AND USER.note='CM帮主描述') OR (USER.name='CMivan' AND USER.note='CMivan描述');
 
复制代码


来到这里,突然就汗了,相当苦闷啊!它竟然没对where里的语句进行解析!没有对表加上相应的前缀!!!!!!



网上有找到这个问题的解决方法!
那就是对where查询里的表,先使用 $this->db->dbprefix('user'); 返回!
$this->db->from("user");
$user = $this->db->dbprefix('user');
$this->db->where("(".$user.".name='CM帮主' and ".$user.".note='CM帮主描述') or (".$user.".name='CMivan' and ".$user.".note='CMivan描述')");


嗯!问题再次被解决了!


-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>

虽然问题是解决了,但是在应用的时候总觉得不顺心!
总觉得这样写的话,很累赘!

一气之下!决定修改AR内核!
找到文件: /system/database/DB_active_rec.php ,在代码底部加上:


PHP复制代码
        //用于支持带括号的检索条件
        function where_on($values = NULL)
        {
                return $this->_where_on($values);
        }
       
        function or_where_on($values = NULL)
        {
                return $this->_where_on($values,'OR ');
        }
         
        function _where_on($values = NULL, $type = 'AND ')
        {
                if ($values === NULL)
                {
                        return;
                }
 
                if ( ! is_array($values))
                {
                        $values = array($values);
                }
               
                $where_on = NULL;
                foreach ($values as $value)
                {
                        $this->ar_whereOR = NULL;
                        if (is_array($value))
                        {
                                $this->ar_whereOR = $this->_where_on_set($value);
                        }
                       
                        if (!empty($this->ar_whereOR))
                        {
                                if ( empty($where_on) )
                                {
                                        $where_on = $this->ar_whereOR;
                                }
                                else
                                {
                                        $where_on.= ' OR ' . $this->ar_whereOR;
                                }
                        }
                }
               
                if( !empty( $where_on ) )
                {
                        $prefix = (count($this->ar_where) == 0 AND count($this->ar_cache_where) == 0) ? '' : $type;
                        $where_on = $prefix . '(' . $where_on . ')';
                       
                        $this->ar_where[] = $where_on;
                        if ($this->ar_caching === TRUE)
                        {
                                $this->ar_cache_where[] = $where_on;
                                $this->ar_cache_exists[] = 'where';
                        }
                        return $this;
                }
               
 
               
        }
       
        function _where_on_set($key, $value = '', $escape = TRUE)
        {
                $key = $this->_object_to_array($key);
 
                if ( ! is_array($key))
                {
                        $key = array($key => $value);
                }
               
                $whereON = NULL;
                $wherePRE = FALSE;
                foreach ($key as $k => $v)
                {
                       
                        if (is_null($v) && ! $this->_has_operator($k))
                        {
                                $k .= ' IS NULL';
                        }
 
                        if ( ! is_null($v))
                        {
                                if ($escape === TRUE)
                                {
                                        $k = $this->_protect_identifiers($k, FALSE, $escape);
 
                                        $v = ' '.$this->escape($v);
                                }
 
                                if ( ! $this->_has_operator($k))
                                {
                                        $k .= ' =';
                                }
                        }
                        else
                        {
                                $k = $this->_protect_identifiers($k, FALSE, $escape);
                        }
 
                        $thisor = $k . $v;
                        if ( !empty($thisor) )
                        {
                                if ( empty($whereON) )
                                {
                                        $whereON = $thisor;
                                }
                                else
                                {
                                        $whereON.= ' AND ' . $thisor;
                                        $wherePRE = TRUE;
                                }
                        }
                }
                if ( $whereON != NULL)
                {
                        if ( $wherePRE )
                        {
                                return '(' . $whereON . ')';
                        }
                        else
                        {
                                return $whereON;
                        }
                }
        }
 
复制代码


OK!可以开始使用这个来查询了!

$this->db->from('user');
$whereON[] = array('user.name'=>'CM帮主','user.note'=>'CM帮主描述');
$whereON[] = array('user.name'=>'CMivan','user.note'=>'CMivan描述');
$this->db->where_on($whereON);

结果终于是我所需要的了:
SQL复制代码
 
SELECT * FROM (`exp_user`) WHERE ((`exp_user`.`name` = 'CM帮主' AND `exp_user`.`note` = 'CM帮主描述') OR (`exp_user`.`name` = 'CMivan' AND `exp_user`.`note` = 'CMivan描述'));
 
复制代码


这里有:
$this->db->where_on() 、 $this->db->or_where_on() 和
$this->db->where() 、 $this->db->or_where()
的原理是一样的,都是为了和前面语句保持AND 或者 OR 的链接关系!就不哆嗦了!


最后! 我写这个出来主要是希望能给遇到相似情况的朋友一些帮助!同时希望大家给点意见,让这个
$this->db->where_on() 的写法可以进一步优化!

评分

参与人数 1威望 +5 收起 理由
Hex + 5

查看全部评分

发表于 2013-3-1 13:53:35 | 显示全部楼层
非常好的东东

本版积分规则