匿名通过本文主要向大家介绍了数据库封装等相关知识,希望本文的分享对您有所帮助
本期要点
深入了解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 语法, 字段匹配多个值

