SQL是Structured Query Language(结构化查询语言)的缩写。SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言。在使用它时,只需要发出“做什么”的命令,“怎么做”是不用使用者考虑的。SQL功能强大、简单易学、使用方便,已经成为了数据库操作的基础,并且现在几乎所有的数据库均支持SQL。
本期要点
深入了解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 关键词:如何写一个属于自己的数据库封装(3)