改进Model类的JOIN方法

浏览:3922 发布日期:2015/03/06
现有的JOIN方法有两个参数,第一参数为关联的表名及条件,第二个参数为关联的类型。在调用的时候表名需要用表的全名,虽然可以用"__表名__"这样的方式,但在使用上感觉还是不方便。

建议的方式是把表名和条件分成两个参数,JOIN方法设三个参数:JOIN(表名,关联条件,关联类型)。代码如下:    /**
     * 查询SQL组装 join
     * @access public
     * @param mixed $join 关联表名
     * @param mixed $condition 关联条件
     * @param string $type JOIN类型
     * @return Model
     */
    public function join($join,$condition,$type='INNER') {
        if(empty($join)) return $this;
        if (!isset($condition)) {
            if (is_array($join) && is_array(current($join))) {
                // 如果为组数,则循环调用join
                foreach ($join as $key => $value) {
                    if (is_array($value) && 2 <= count($value)) {
                        $this->join($value[0],$value[1],isset($value[2])?$value[2]:$type);
                    }
                }
            } else {
                $this->_join($join,$condition); // 兼容原来的join写法
            }
        } elseif (in_array($condition, array('INNER','LEFT','RIGHT','ALL'))) {
            $this->_join($join,$condition);  // 兼容原来的join写法
        } else {
            $prefix = $this->tablePrefix;
            if (is_array($join)) {
                if (0 !== key($join)) {
                    $table = key($join) . ' ' . current($join);
                } else {
                    $table = current($join);
                }
                if (!isset($join[1]) || false != $join[1]) {
                    $table = $prefix . $table;
                }
            } else {
                $join = ltrim($join);
                if (0 === strpos($join, '__')) {
                    //将__TABLE_NAME__字符串替换成带前缀的表名
                    $table  = preg_replace_callback("/__([A-Z0-9_-]+)__/sU", function($match) use($prefix){ return $prefix.strtolower($match[1]);}, $join);                                    
                } elseif (false === strpos($join, '(') && 0 !== strpos($join, $prefix)) {
                    $table = $prefix . $join;
                } else {
                    $table = $join;
                }
            }
            if (is_array($condition)) {
                $condition = implode(' AND ', $condition);
            }
            $this->options['join'][] = $type.' JOIN '.$table.' ON '.$condition;
        }
        return $this;
    }

    /**
     * 查询SQL组装 _join
     * @access public
     * @param mixed $join
     * @param string $type JOIN类型
     * @return Model
     */
    public function _join($join,$type='INNER') {
        $prefix =   $this->tablePrefix;
        if(is_array($join)) {
            foreach ($join as $key=>&$_join){
                $_join  =   preg_replace_callback("/__([A-Z0-9_-]+)__/sU", function($match) use($prefix){ return $prefix.strtolower($match[1]);}, $_join);
                $_join  =   false !== stripos($_join,'JOIN')? $_join : $type.' JOIN ' .$_join;
            }
            $this->options['join']      =   $join;
        }elseif(!empty($join)) {
            //将__TABLE_NAME__字符串替换成带前缀的表名
            $join  = preg_replace_callback("/__([A-Z0-9_-]+)__/sU", function($match) use($prefix){ return $prefix.strtolower($match[1]);}, $join);
            $this->options['join'][]    =   false !== stripos($join,'JOIN')? $join : $type.' JOIN '.$join;
        }
        return $this;
    }
为了与原来的JOIN方法兼容,所以把Model类中原JOIN方法改名成_join,并判断join方法第二个参数,值为('INNER','LEFT','RIGHT','ALL')中的一个时就调用_join方法。此时调用方法就与原来的一样,关联条件需要和表名写在一起。

调用说明:M('User')->alias('u')->join('group g', 'u.id=g.user_id')->select();
/* select * form tp_user u join tp_group g on u.id=g.user_id; */
group表自动加上了表前缀tp_。

第一个参数也可以是一个数组,如:M('User')->alias('u')->join(array('group'=>'g'), 'u.id=g.user_id')->select();
/* select * form tp_user u join tp_group g on u.id=g.user_id; */
生成的sql语句和前面的一样。


如果不想添加默认的表前缀,可以这样调用:M('User')->alias('u')->join(array('group'=>'g', false), 'u.id=g.user_id')->select();
/* select * form tp_user u join group g on u.id=g.user_id;  */
此时group不再自动加上前缀。


支持多个join连写,如:M('User')->alias('u')->join('group g', 'u.id=g.user_id')->join('role r', 'g.id=r.group_id')->select();也可以以数组形式调用$join = array(array('group g', 'u.id=g.user_id'), array('role r', 'g.id=r.group_id')); M('User')->alias('u')->join($join)->select();此时join方法不得传入第二和第三参数。
评论(
后面还有条评论,点击查看>>