CM帮主 发表于 2012-3-19 12:16:16

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

本帖最后由 CM帮主 于 2012-3-19 14:06 编辑

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

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

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描述');

结果返回的查询语句是这样的:

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描述')");

结果返回的查询语句是这样的:

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_';


新问题就来了,原来的语句查询的结果变成了这样:

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 ,在代码底部加上:


      //用于支持带括号的检索条件
      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);

结果终于是我所需要的了:

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() 的写法可以进一步优化!

630088892 发表于 2013-3-1 13:53:35

非常好的东东
页: [1]
查看完整版本: 突破在使用AR过程中所遇到的一个瓶颈!