匿名通过本文主要向大家介绍了数据库封装等相关知识,希望本文的分享对您有所帮助
本期要点
深入了解php函数的各种辅助函数 PHP核心语法:函数
理解什么是可变参数函数, ...$var, PHP5.6新特性介绍
compact函数的用法 PHP: compact - Manual
list函数的用法 PHP: list - Manual
PHP魔术方法
开始之前
本期说的是SQL中的查询语句, 由于复杂程度和多个类之间的关联性不是Connector篇那么简单, 故此, 这一回需要一口气讲解Builder类, Grammar类, 还有Model类, 当然, 只是查询部分
Builder.php
请求构建器, 所有类之间的桥梁
<?php /** * 请求构建器 */ class Builder { // 连接数据库, Connector类 protected $connector; // 生成SQL语法,Grammar类 protected $grammar; // 连接的Model, Model类 protected $model; // SQL查询语句中条件的值 // 虽然列出了全部, 但本教程只实现了where,其余的因为懒(理直气壮),请自行实现, 逻辑和where函数大致 protected $bindings = [ 'select' => [], 'join' => [], 'where' => [], 'having' => [], 'order' => [], 'union' => [], ]; // select 语法想要查看的字段 public $columns; // 过滤重复值 public $distinct = false; // 需要查询的表 public $from; // 所有join 语法 public $joins; // 所有where 语法 public $wheres; // group 语法 public $groups; // having 语法 public $havings; // order by 语法 public $orders; // 限制数据库返回的数据量, limit语法 public $limit; // 需要略过的数据量, offset语法 public $offset; // 数据写保护, 开启后该条数据无法删除或改写 public $writeLock = false;
接下来是函数
_construct - 生成实例后第一步要干嘛
function construct() { // 新建两个实例 // 如果已经理解Connector的原理后自然明白这个Connector实例已经联通了数据库 $this->connector = new Connector; $this->grammar = new Grammar; }
select - 选择想看到的column, 默认为全部, 即 '*'
public function select($columns = ['*']) { // $columns只能存入数组, 所以需要判定, 如果不是, 将所有参数合成一个数组再存入 // 这是一个更人性化的设定, 用户可以选择以下两种调用方式 // select(['first_name', 'last_name']), 以数组的方式 // select('first_name', 'last_name'), 以参数的方式 // 最后一点, 你可以发现所有函数最后都会存入对应的Builder属性中 // 这和你在做饭前先处理材料是同一个道理, 也就是预处理 $this->columns = is_array($columns) ? $columns : func_get_args(); return $this; }
distinct - 过滤重复值
public function distinct() { // 开启过滤 $this->distinct = true; return $this; }
from - 设置表名
public function from($table) { $this->from = $table; return $this; }
join - 连接两个表的join语法, 默认为inner join
/** * @param string $table 需要连接的副表名 * 为什么主键和外键可以单个或数组呢 * 原因是join语法可以on多个键 * @param string/array $foregin 外键 * @param string/array $primary 主键 * @param string $type 连接方式, 默认inner * @return Builder 返回Builder实例 */ 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; }
join的各种变形, 只实现常见的三种join, 其余请自行添加
// 所有逻辑同join(), 不过这是left join public function leftJoin($table, $foregin , $primary) { return $this->join($table, $foregin , $primary, 'left'); } // 所有逻辑同join(), 不过这是right join public function rightJoin($table, $foregin , $primary) { return $this->join($table, $foregin , $primary, 'right'); }
addBinding - 储存各种sql条件所附带的值
/** * @param string/array $value 字段匹配的值 * @param string $type 条件类型, 默认为where, 具体查看$bindings */ public function addBinding($value, $type = 'where') { // 如果$type并不是$bindings的键, 跳出错误 if (!array_key_exists($type, $this->bindings)) throw new InvalidArgumentException("Invalid binding type: {$type}."); // 如果$value是数组,将其与之前存入的值整合为一维数组 if (is_array($value)) $this->bindings[$type] = array_values(array_merge($this->bindings[$type], $value)); // 反之, 直接存入最后一位即可 else $this->bindings[$type][] = $value; // 返回Builder实例 return $this; }
where - sql中的条件, where语法
where()有两种不同的调用方式
接下来多个函数都有两种调用方式, 请从之后的代码逻辑中自行领悟
以参数的方式, 默认为'='
Actor::select('first_name', 'last_name') ->where('first_name', 'NICK') ->where('last_name','!=', 'WAHLBERG') ->first()
以数组的方式, 这方式有局限性, 仅能匹配 字段等于值 的情况
Actor::select('first_name', 'last_name') ->where(['first_name'=> 'NICK', 'last_name'=> 'WAHLBERG']) ->first()
接下来看代码
public function where($column, $operator = null, $value = null, $boolean = 'and') { // 判定$column是否为数组 if (is_array($column)) { // 如果是数组, 循环再调用本函数,where() foreach ($column as $key => $value) $this->where($key, "=", $value, $boolean); }else { // 反之, 判定参数数量和$value是否为空, 如果为真,这意味着用户省略了'=',自动添加 if(func_num_args() == 2 || is_null($value)) list($operator, $value) = ['=', $operator]; // 最简单原始的条件查询, 所以$type值为Basic $type = "Basic"; // 将处理过的条件存入$wheres $this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean'); // 将字段需要匹配的值存入$bindings中的where $this->addBinding($value, 'where'); } // 返回Builder实例 return $this; }
where的各种变形
// 所有逻辑同where(), 不过这是or where public function orWhere($column, $operator = null, $value = null) { return $this->where($column, $operator, $value, 'or'); } /** * where in 语法, 字段匹配多个值