php数据库封装6,如何写一个属于自己的数据库封装(6) - 查询 - WHERE篇

开始之前

WHERE 篇中, where 的各种应用方式都来自 Laravel

本篇将在 Builder.php 的每个 where 函数最后边给出例子方便理解

Builder.php

where - 基本的 where 用法

where 函数用法多样, 请参考例子

public function where($column, $operator = null, $value = null, $boolean = 'and') {

// 判定$column是否为数组

if (is_array($column)) {

// 如果是数组, 循环调用 where()

foreach ($column as $condition) {

// 一组只有两个参数意味着 $operator 被省略了, 自动加上默认的 '='

if (sizeof($condition)===2)

list($condition[1], $condition[2]) = ['=', $condition[1]];

// 不存在第四个参数意味着这是默认的 and 条件

if(!isset($condition[3]))

$condition[3] = $boolean;

// 这种调用方式必须提供最少2种参数, $columns, $operator, $value, $boolean可以选择默认, '='

$this->where($condition[0], $condition[1], $condition[2], $condition[3]);

}

// 判定$column是否为闭包函数

}elseif ($column instanceof Closure) {

// 如果是, 调用 whereNested()

// whereNested() 实现了高级 where 语句, 开发者可以实现的 SQL 语句 如下

// select * from `actor` where `actor_id` = '5' or (`actor_id` = '6' and `first_name` != 'JACK')

return $this->whereNested($column, $boolean);

}else {

// 反之, 判定参数数量和$value是否为空, 如果是,这意味着用户省略了'=',自动添加

if(func_num_args() == 2 || is_null($value))

list($operator, $value) = ['=', $operator];

// 最简单原始的条件查询, 所以 $type 值为Basic

$type = "Basic";

// column 如果没有附上表名, 那就自动加上

if (!preg_match('/\./', $column))

$column = $this->model->getTable().".$column";

// 将处理过的条件存入 $wheres

$this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean');

// 将字段需要匹配的值存入 $bindings中的 where

$this->addBinding($value, 'where');

}

// 返回 Builder 实例

return $this;

}

WHERE 的例子

1.以参数的方式 - 选择默认 '='

Actor::where('first_name', 'PENELOPE')->get();

2.以参数的方式 - 提供运算符

Actor::where('first_name', '!=', 'PENELOPE')->get();

3.以数组的方式 - 允许省略运算符和提供运算符两种方式混合使用

Actor::where([

['first_name', '!=', 'PENELOPE'],

['last_name', 'CHASE']

])->get();

4.允许多次调用

Actor::where('first_name', '!=', 'PENELOPE')

->where('last_name', 'CHASE')

->get();

5.以闭包函数来调用子句

select * from Actor where Actor.first_name = 'PENELOPE' and (Actor.last_name = 'PINKETT' or Actor.last_name = 'CRONYN')

Actor::where('first_name', 'PENELOPE')

->where(function ($builder) {

$builder->where('last_name', 'PINKETT')

->orWhere('last_name', 'CRONYN'); // orWhere() 将在下方给出

})

->get();

whereNested - 实现嵌套式的 where 语句

whereNested() 仅供内部函数使用以实现闭包函数内的 where 子句, 所以没有例子

public function whereNested(Closure $callback, $boolean = 'and') {

// 创建一个新的 Builder 实例, 然后在闭包函数内应用它

call_user_func($callback, $query = (new static)->from($this->from));

// 这是一个嵌套

$type = 'Nested';

// 处理过的条件存入 $wheres

$this->wheres[] = compact('type', 'query', 'boolean');

// 将字段需要匹配的值存入 $bindings中的 where

$this->addBinding($query->getBindings(), 'where');

// 返回 Builder 实例

return $this;

}

orWhere - 所有逻辑同where(), 不过这是or where

例子参照上面的 where 函数

public function orWhere($column, $operator = null, $value = null) {

return $this->where($column, $operator, $value, 'or');

}

whereBetween - 字段匹配限定范围内的值

public function whereBetween($column, array $values, $boolean = 'and', $not = false) {

// 类型是 between

$type = 'Between';

// 处理过的条件存入 $wheres

$this->wheres[] = compact('column', 'type', 'boolean', 'not');

// 将字段需要匹配的值存入 $bindings中的 where

$this->addBinding($values, 'where');

// 返回 Builder 实例

return $this;

}

whereBetween 的例子

select * from Actor where Actor.actor_id between 5 and 8

Actor::whereBetween('actor_id', [5,8])->get();

whereBetween 的各种变体

// 所有逻辑同 whereBetween(), 不过这是 or where between

public function orWhereBetween($column, array $values) {

return $this->whereBetween($column, $values, 'or');

}

// 所有逻辑同 whereBetween(), 不过这是 where not between

public function whereNotBetween($column, array $values, $boolean = 'and') {

return $this->whereBetween($column, $values, $boolean, true);

}

// 所有逻辑同 whereNotBetween(), 不过这是 or where not between

public function orWhereNotBetween($column, array $values) {

return $this->whereNotBetween($column, $values, 'or');

}

whereIn - 字段匹配多个值

public function whereIn($column, $values, $boolean = 'and', $not = false) {

// 判定条件查询的类型, false = where in ($value),true = where not in ($value)

$type = $not ? 'NotIn' : 'In';

// 将条件存入$wheres

$this->wheres[] = compact('type', 'column', 'values', 'boolean');

// 循环将字段需要匹配的值存入$bindings中的where

foreach ($values as $value)

$this->addBinding($value, 'where');

// 返回Builder实例

return $this;

}

whereIn 的例子

select * from Actor where Actor.actor_id in (5, 6, 8)

Actor::whereIn('actor_id', [5, 6, 8])->get();

whereIn 的各种变体

// 所有逻辑同whereIn(), 不过这是or where in

public function orWhereIn($column, $values) {

return $this->whereIn($column, $values, 'or');

}

// 所有逻辑同whereIn(), 不过这是and where not in

public function whereNotIn($column, $values, $boolean = 'and') {

return $this->whereIn($column, $values, $boolean, true);

}

// 所有逻辑同whereNotIn(), 不过这是or where not in

public function orWhereNotIn($column, $values) {

return $this->whereNotIn($column, $values, 'or');

}

whereNull - where $coulmn is null 语法, 搜索字段为空的数据

public function whereNull($column, $boolean = 'and', $not = false) {

// 判定条件查询的类型, false = where $column is null,true = where $column is not null

$type = $not ? 'NotNull' : 'Null';

// 将条件存入 $wheres

$this->wheres[] = compact('type', 'column', 'boolean');

// 返回 Builder 实例

return $this;

}

whereNull 的例子

select * from Actor where Actor.last_name is null

Actor::whereNull('last_name')->get();

whereNull 的各种变体

// 所有逻辑同whereNull(), 不过这是or where $column is null

public function orWhereNull($column) {

return $this->whereNull($column, 'or');

}

// 所有逻辑同whereNull(), 不过这是and where $column is not null

public function whereNotNull($column, $boolean = 'and') {

return $this->whereNull($column, $boolean, true);

}

// 所有逻辑同whereNotNull(), 不过这是or where $column is not null

public function orWhereNotNull($column) {

return $this->whereNotNull($column, 'or');

}

whereColumn - 用于比较字段, 比方说筛选出支出大于收入的记录

public function whereColumn($first, $operator = null, $second = null, $boolean = 'and') {

// 判定$column是否为数组

if (is_array($first)) {

// 如果是数组, 循环调用 whereColumn()

foreach ($first as $condition) {

// 一组只有两个参数意味着 $operator 被省略了, 自动加上默认的 '='

if (sizeof($condition)===2)

list($condition[1], $condition[2]) = ['=', $condition[1]];

// 不存在第四个参数意味着这是默认的 and 条件

if(!isset($condition[3]))

$condition[3] = $boolean;

// 这种调用方式必须提供最少2种参数, $columns, $operator, $value, $boolean可以选择默认, '='

$this->whereColumn($condition[0], $condition[1], $condition[2], $condition[3]);

}

}else {

// 反之, 判定参数数量和 $second 是否为空, 如果是,这意味着用户省略了'=',自动添加

if(func_num_args() == 2 || is_null($second))

list($operator, $second) = ['=', $operator];

// 类型为 Column

$type = 'Column';

// 将条件存入 $wheres

$this->wheres[] = compact(

'type', 'first', 'operator', 'second', 'boolean'

);

}

// 返回 Builder 实例

return $this;

}

whereColumn 的例子

select * from Actor where Actor.first_name = Actor.last_name

Actor::whereColumn('first_name', '=', 'last_name')->get()

或省略 '='

Actor::whereColumn('first_name', 'last_name')->get()

whereColumn 的变体

// 所有逻辑同 whereColumn(), 不过这是 or where $column1 compare $column2

public function orWhereColumn($first, $operator = null, $second = null) {

return $this->whereColumn($first, $operator, $second, 'or');

}

Grammar.php

配合注释味道更佳

compileWheres - 编译where语句

protected function compileWheres(Builder $query) {

$sql = [];

// 类似与compileComponents(), 循环Builder实例中的$wheres

foreach ($query->wheres as $where) {

// 根据不同的$type来进行编译

$method = "where{$where['type']}";

// 返回的部分语句先收入数组

$sql[] = $where['boolean'].' '.$this->$method($query, $where);

}

// 最后将$sql数组连接起来, 删掉最前面的and或or在返回

return 'where '.preg_replace('/and |or /i', '', implode(" ", $sql), 1);

}

whereBasic - 编译最基本的 where 用法

protected function whereBasic(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点

// 是, 就意味着前缀已经附带了表名

// 否, 为之后的字段添上表名

// 因为 join 存在副表, 所以部分 $where 可能有附带表名, 这时候就不用添加了

$table = !preg_match('/\./', $where['column']) ? $query->from."." : '';

// 返回添上表名的字段,和表达式, 再一个问号

// 为何使用问号而不是:变量名? 因为:变量名存在太多局限性,不能标点符号,不能数字开头

return $table.$where['column'].' '.$where['operator'].' ?';

}

whereNested - 编译 where 嵌套分组用法

protected function whereNested(Builder $query, $where) {

return '('.str_replace('where ', '', $this->compileWheres($where['query'])).')';

}

where between - 编译 where between 用法

protected function whereBetween(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点, 同理 whereBasic()

$table = !preg_match('/\./', $where['column']) ? $query->from."." : '';

// 检测 $not, 如果是 true, 添上 'not'

$between = $where['not'] ? 'not between' : 'between';

return $table.$where['column'].' '.$between.' ? and ?';

}

where in - 编译 where in 用法

protected function whereIn(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点, 同理 whereBasic()

$table = !preg_match('/\./', $where['column']) ? $query->from."." : '';

// 有多少个匹配值那就连接多少个问号

$values = implode(', ', array_fill(0, sizeof($where['values']), '?'));

// 返回 where in 语句

return $table.$where['column'].' in ('.$values.')';

}

where not in - 编译 where not in 用法

protected function whereNotIn(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点, 同理 whereBasic()

$table = !preg_match('/\./', $where['column']) ? $query->from."." : '';

// 有多少个匹配值那就连接多少个问号

$values = implode(', ', array_fill(0, sizeof($where['values']), '?'));

// 返回 where not in 语句

return $table.$where['column'].' not in ('.$values.')';

}

where null - 编译 where null 用法

protected function whereNull(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点, 同理 whereBasic()

$table = !preg_match('/\./', $where['column']) ? $query->from."." : '';

// 返回 where is null 语句

return $table.$where['column'].' is null';

}

where not null - 编译 where not null 用法

protected function whereNotNull(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点, 同理 whereBasic()

$table = !preg_match('/\./', $where['column']) ? $query->from."." : '';

// 返回where is not null 语句

return $table.$where['column'].' is not null';

}

where column - 编译 where column 用法

protected function whereColumn(Builder $query, $where) {

// 检测 $where[column] 是否存在小数点, 同理 whereBasic()

$table = !preg_match('/\./', $where['first']) ? $query->from."." : '';

// 为了避免开发者疏忽, $first 和 $second 其中一个没有加上前缀

if($table !== '')

$where['second'] = str_replace("$table.", '', $where['second']);

return $table.$where['first'].' '.$where['operator'].' '.$table.$where['second'];

}

完整代码

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值