美文网首页程序员PHP经验分享PHP实战
如何写一个属于自己的数据库封装(5) - 查询 - JOIN篇

如何写一个属于自己的数据库封装(5) - 查询 - JOIN篇

作者: 幼年期程序猿 | 来源:发表于2017-05-26 16:35 被阅读0次

    上一期 如何写一个属于自己的数据库封装(4) - 查询 - 入门篇用法
    下一期 如何写一个属于自己的数据库封装(6) - 查询 - WHERE篇

    开始之前

    本篇仅实现了 inner join, left join, 和 right join
    本篇为关联多个模型的打下了基础, 至于如何实现, 请移步 JOIN 的衍生篇 - 关联关系篇


    Builder.php

    • join - 默认inner join
        public function join($table, $foregin , $primary, $type = 'inner') {
            // 判定外键变量的数据类型
            if(is_array($foregin)) {
                // 如果是数组, 循环加上副表名在前头
                foreach($foregin as &$f)
                    $f = $table.".".$f;
            }else {
                // 反之, 不需循环直接加
                $foregin = $table.".".$foregin;
            }
    
            // 与$foreign的逻辑同理
            if(is_array($primary)) {
                foreach($primary as &$p)
                    $p = $this->from.".".$p;
            }else {
                $primary = $this->from.".".$primary;
            }
    
            // 将所有经过处理的参数收入$joins待用
            $this->joins[] = (object)[
                'from' => $this->from,
                'table' => $table,
                'foregin' => $foregin,
                'primary' => $primary,
                'type' => $type
            ];
    
            // 返回Builder实例
            return $this;
        }
    
    • leftJoin
    // 所有逻辑同join(), 不过这是left join
        public function leftJoin($table, $foregin , $primary) {
            return $this->join($table, $foregin , $primary, 'left');
        }
    
    • rightJoin
    // 所有逻辑同join(), 不过这是right join
        public function rightJoin($table, $foregin , $primary) {
            return $this->join($table, $foregin , $primary, 'right');
        }
    

    Grammar.php

    • compileJoins - 编译join语句
        protected function compileJoins(Builder $query, $joins) {
            $sql = [];
            foreach ($joins as $join) {
                // 如果存在多个副键和主键
                if(is_array($join->foregin) && is_array($join->primary)) {
                    $on = [];
                    // 循环键的数量, 将之与对应的主键组合
                    for($i=0; $i<sizeof($join->foregin); $i++)
                        $on[] = $join->foregin[$i]." = ".$join->primary[$i];
                    // 最后再将所有句子用and连接
                    $on = implode(' and ', $on);
                } else {
                //反之, 直接连接即可
                    $on = "$join->foregin = $join->primary";
                }
                // 附上join的类型和副表
                $sql[] = trim("{$join->type} join {$join->table} on $on");
            }
    
            // 连接再返回
            return implode(' ', $sql);
        }
    

    JOIN 函数返回的数据库数据不可再操作, update() 和 delete() 都只会影响主表的数据, 副表无法操作


    例子

    本篇代码非常简练, 请配合注释食用, 还不明白? 看下方例子

    select * from Actor inner join film_actor on film_actor.actor_id = Actor.actor_id
    
    Actor::join('film_actor', 'actor_id', 'actor_id')->get()
    

    返回结果

    array (size=5462)
      0 =>
        object(Actor)[5473]
          public 'actor_id' => string '1' (length=1)
          public 'first_name' => string 'PENELOPE' (length=8)
          public 'last_name' => string 'GUINESS' (length=7)
          public 'last_update' => string '2006-02-15 05:05:03' (length=19)
          public 'film_id' => string '1' (length=1)
      1 =>
        object(Actor)[5477]
          public 'actor_id' => string '1' (length=1)
          public 'first_name' => string 'PENELOPE' (length=8)
          public 'last_name' => string 'GUINESS' (length=7)
          public 'last_update' => string '2006-02-15 05:05:03' (length=19)
          public 'film_id' => string '23' (length=2)
    ......
    

    所有 join 函数调用方式一致, 故不赘述

    完整代码

    源代码放在coding.net里, 自己领

    上一期 如何写一个属于自己的数据库封装(4) - 查询 - 入门篇用法
    下一期 如何写一个属于自己的数据库封装(6) - 查询 - WHERE篇

    相关文章

      网友评论

        本文标题:如何写一个属于自己的数据库封装(5) - 查询 - JOIN篇

        本文链接:https://www.haomeiwen.com/subject/rwjxfxtx.html