360教程:是一个免费提供流行杀毒软件教程、在线学习分享的学习平台!

如何写一个属于自己的数据库封装(3)

时间:2022-10-23作者:未知来源:360教程人气:

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)




Copyright © 2012-2018 360教程(http://www.360sd.cn) .All Rights Reserved 网站地图 友情链接

免责声明:本站资源均来自互联网收集 如有侵犯到您利益的地方请及时联系管理删除,敬请见谅!

QQ:1006262270   邮箱:kfyvi376850063@126.com   手机版