even

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
<?php
header('content-type:text/html;charset=utf8');
ini_set('display_errors', true);

$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
final Class DB
{
    private static $db;

    private function __clone(){}

    private function __construct() {
        global $config;
        $mysqli =  new Mysqli($config['host'], $config['user'], $config['password'],$config['dbname'], $config['port']);
        //如果没有错误则返回0如果有错误,那么返回对应的错误编号
        if($mysqli->connect_errno) {
            die('连接错误,错误信息是'.$mysqli->connect_error);
        }
        //设置字符集
        $mysqli->set_charset('utf8');
        self::$db = $mysqli;
    }

    static function getInstance()
    {
        if (!self::$db instanceof Mysqli) {
            new self();
        }
        return self::$db;
    }
}

class Expression {
    private $str;
    public function __construct(string $str) {
        $this->str = $str;
    }
    public function getStr() {
        return $this->str;
    }
}

trait Filter {
    private $sql;
    private $currentType;  //0为自写的sql语句,1为查询,2为插入,3为修改,4为删除
    private $selectSql = null;
    private $whereSql = null;
    private $leftJoinSql = null;
    private $rightJoinSql = null;
    private $innerJoinSql = null;
    private $groupBySql = null;
    private $havingSql = null;
    private $orderBySql = null;
    private $table = null;
    private function quoteField($val, $split = null) {
        if(is_object($val) && $val instanceof Expression) {
            return $val->getStr();
        }
        if(!$split){
            return sprintf('`%s`',trim($val));
        }
        $tempArr = explode($split,$val);
        $newArr = [];
        $keyWord = ['AS', 'ASC', 'DESC'];
        array_walk($tempArr, function($value)use(&$newArr, $keyWord) {
            $temp = null;
            if($value) {
                switch(true) {
                    case in_array(strtoupper($value), $keyWord): array_push($newArr, strtoupper($value)); break;
                    case stripos($value, '.'): array_push($newArr, $this->quoteField($value, '.')); break;
                    default : array_push($newArr, sprintf('`%s`',trim($value)));
                }
            }
        });
        return implode($newArr, $split);
    }

    private function quoteValue($val) {
        $str = null;
        switch(true) {
            case preg_match('/\'\"/', $val): $str = $val; break;
            case is_string($val) : $str = sprintf('"%s"', $val); break;
            case is_numeric($val) : $str = $val;
        }
        return $str ?? '';
    }

    private function commonDeal(array $args, &$handle) {
        $arr = [];
        foreach($args as $key => $val){
            array_push($arr, $this->quoteField($val,','));
        }
        count($arr) > 0 ? $handle = implode($arr, ','): null;
    }

    /**select 语句
     * @return $this
     */
    public function select () {
        $args = is_array(func_get_arg(0))? func_get_arg(0) : func_get_args();
        $arr = [];
        $isAll = false;
        foreach($args as $key=>$val) {
            if(is_string($val) && preg_match('/\(.*?\)/', $val)) {
                $str = preg_replace_callback('/([^\(\)]*)\((.*?)\)([^\(\)]*)/',function ($argArr) {
                    list(, $f, $s, $t) = $argArr;
                    if($s === '*') {
                        return sprintf('%s(%s) %s' , strtoupper($f), $s, $this->quoteField($t, ' '));
                    }
                    return sprintf('%s(%s) %s',strtoupper($f), $this->quoteField($s, ' '), $this->quoteField($t, ' '));
                }, $val);
                array_push($arr, $str);
            }else{
                array_push($arr, $this->quoteField($val, ' '));
                if($val === '*'){
                    $isAll = true;
                    break;
                }
            }
        }
        $this->currentType = 1;
        count($arr) > 0 ? $this->selectSql = ($isAll === true ? true : implode($arr, ',')): null;
        return $this;
    }

    /**group by 方法
     * @return $this
     */
    public function groupBy() {
        $args = is_array(func_get_arg(0))? func_get_arg(0) : func_get_args();
        $this->commonDeal($args, $this->groupBySql);
        $this->groupBySql =$this->groupBySql? sprintf(' GROUP BY %s', $this->groupBySql) : '';
        return $this;
    }

    /**order by 方法
     * @return $this
     */
    public function orderBy(){
        $arg = func_get_arg(0);
        $arr = [];
        if(is_array($arg)) {                //如果传入的是一个数组
            array_walk($arg, function($val, $key)use(&$arr) {
                array_push($arr, sprintf('%s %s', $this->quoteField($key), $val == 3? 'SORT_DESC' : 'SORT_ASC'));
            });
        } else if(is_string($arg)) {        //如果传入的是一个字符串
            $tempArr = explode(',', $arg);
            array_walk($tempArr, function($val)use(&$arr) {
                array_push($arr, $this->quoteField($val, ' '));
            });
        }
        count($arr) > 0? $this->orderBySql = sprintf(' ORDER BY %s', implode(',', $arr)) : null;
        return $this;
    }

    /**from 方法
     * @param string $table
     * @return $this
     */
    public function from (string $table) {
        $this->table = $this->quoteField($table, ' ');
        return $this;
    }

    /**where 与 having 的内部处理函数
     * @param $arg1
     * @param null $arg2
     * @return array|string|string[]|null
     */
    private function conditionFilter($arg1, $arg2 = null) {
        if($arg1 && !$arg2) {
            if(is_string($arg1)) {
                return $arg1;
            } else if(is_array($arg1)) {
                $tempArr = [];
                $setArr1 = ['LIKE', '>=', '<=', '=', '>', '<'];
                $setArr2 = ['AND', 'OR'];
                $link = strtoupper(reset($arg1));
                if(in_array($link, $setArr1)) {
                    $key = count($arg1) >= 2 ? next($arg1) : null;
                    $val = count($arg1) >= 3 ? next($arg1) : null;
                    $sign = count($arg1) >= 4 ? next($arg1) : true;
                    return !$key || !$val ? '' : (strtoupper(trim($link)) === 'LIKE'? "{$this->quoteField($key)} LIKE ".($sign? "\"%{$val}%\"" : "\"{$val}\""):"{$this->quoteField($key,' ')} {$link} {$val}");
                }else if (in_array($link, $setArr2)) {
                    while($temp = next($arg1)){
                        array_push($tempArr, is_array($arg1)? $this->conditionFilter($temp): $temp);
                    }
                    $link = strtoupper($link);
                    return implode(' '.$link.' ',$tempArr);
                }
                foreach($arg1 as $key=>$val) {
                    array_push($tempArr, sprintf('%s = %s', $this->quoteField($key), $this->quoteValue($val)));
                }
                return implode(',', $tempArr);
            }
        }else if($arg2 && is_array($arg2)) {
            return preg_replace_callback('/(?:^|,{1}|\s)?(.*?)(=|>|<|<=|>=|\s*like\s*){1}\s*(:[^,]*)\s*(,{1}|$)/', function($all)use($arg2){
                list(, $name, $sign, $key, $split) = $all;
                if(!$arg2[trim($key)]) {
                    die("where语句中的{$key}没有对应的值,是否是因为数组引号里空格的原因");
                }
                strtoupper(trim($sign)) === 'LIKE'? $arg2[trim($key)] = "\"%{$arg2[trim($key)]}%\"" : null;
                return sprintf('%s %s %s %s', $this->quoteField($name,'.'), strtoupper($sign), $arg2[trim($key)], $split);
            }, $arg1);
        }
        return '';
    }

    public function where(){
        $count = func_num_args();
        $first = $count >= 1? func_get_arg(0) : null;
        $second =$count >= 2? func_get_arg(1) : null;
        $res = $this->conditionFilter($first, $second);
        $this->whereSql =$res ? ' WHERE '.$res : '';
        return $this;
    }

    public function having(){
        $count = func_num_args();
        $first = $count >= 1? func_get_arg(0) : null;
        $second =$count >= 2? func_get_arg(1) : null;
        $res = $this->conditionFilter($first, $second);
        $this->havingSql =$res ? ' Having '.$res : '';
        return $this;
    }

    private function dealJoinFunc($arg1, $arg2) {
        if(!$arg1 || !$arg2) {
            die('表的连接的参数有问题');
        }
        if(is_string($arg1)) {
            list($first, $second) = preg_split('/\s*=\s*/', $arg2);
            return sprintf('%s ON %s = %s', $this->quoteField($arg1,' '), $this->quoteField($first,'.'),$this->quoteField($second, '.'));
        }else if(is_array($arg1)) {
            $val = reset($arg1);
            $key = key($arg1);
            list($first, $second) = preg_split('/\s*=\s*/', $arg2);
            if($val instanceof Query){
                $str = sprintf('(%s) AS %s', $val->getSql(), $this->quoteField($key));
                return sprintf('%s ON %s = %s', $str, $this->quoteField($first,'.'),$this->quoteField($second, '.'));
            }
        }
        return '';
    }

    public function leftJoin() {
        $count = func_num_args();
        $first = $count >= 1? func_get_arg(0) : null;
        $second =$count >= 2? func_get_arg(1) : null;
        $res = $this->dealJoinFunc($first, $second);
        $this->leftJoinSql = $res ? ' LEFT JOIN '.$res : '';
        return $this;
    }

    public function rightJoin() {
        $count = func_num_args();
        $first = $count >= 1? func_get_arg(0) : null;
        $second =$count >= 2? func_get_arg(1) : null;
        $res = $this->dealJoinFunc($first, $second);
        $this->rightJoinSql = $res ? ' RIGHT JOIN '.$res : '';
        return $this;
    }

    public function innerJoin() {
        $count = func_num_args();
        $first = $count >= 1? func_get_arg(0) : null;
        $second =$count >= 2? func_get_arg(1) : null;
        $res = $this->dealJoinFunc($first, $second);
        $this->innerJoinSql = $res ? ' INNER JOIN '.$res : '';
        return $this;
    }

    public function delete() {
        $this->currentType = 4;
        $count = func_num_args();
        $table = $count >= 1? func_get_arg(0) : null;
        $first = $count >= 2? func_get_arg(1) : null;
        $second =$count >= 3? func_get_arg(2) : null;
        $res = $this->conditionFilter($first, $second);
        $this->sql = sprintf('DELETE FROM %s', $this->quoteField($table)).$this->whereSql =$res ? ' WHERE '.$res : '';
        return $this;
    }

    public function update() {
        $this->currentType = 3;
        $count = func_num_args();
        $table = $count >= 1? func_get_arg(0) : null;
        $first = $count >= 2? func_get_arg(1) : null;
        $second =$count >= 3? func_get_arg(2) : null;
        $third =$count >= 4? func_get_arg(3) : null;
        $res = $this->conditionFilter($second, $third);
        $valArr = [];
        if(is_string($first)) {
            array_push($valArr, $first);
        }else if (is_array($first)) {
            array_walk($first, function($val, $key)use(&$valArr) {
                array_push($valArr , sprintf('%s = %s', $this->quoteField($key), $this->quoteValue(trim($val))));
            });
        }
        $this->sql = sprintf('UPDATE %s SET %s ', $this->quoteField($table), implode(',', $valArr)).$this->whereSql =$res ? ' WHERE '.$res : '';
        return $this;
    }

    public function insert() {
        $this->currentType = 2;
        $count = func_num_args();
        if($count < 2) {
            die('传入的参数不足以启动Insert语句');
        }
        $table = $count >= 1? func_get_arg(0) : null;
        $first = $count >= 2? func_get_arg(1) : null;
        $keyArr = [];
        $valArr = [];
        if(is_string($first)) {
            array_push($valArr, $first);
        }else if (is_array($first)) {
            array_walk($first, function($val, $key)use(&$keyArr, &$valArr) {
                array_push($keyArr , $this->quoteField(trim($key)));
                array_push($valArr , $this->quoteValue(trim($val)));
            });
        }
        $this->sql = sprintf('INSERT INTO %s (%s) VALUES (%s) ', $this->quoteField($table), implode(',', $keyArr), implode(',', $valArr));
        return $this;
    }

    public function getSql() {
        if($this->currentType === 1){
            $str = sprintf('SELECT %s FROM %s', $this->selectSql === true? '*' : $this->selectSql, $this->table);
            $str.= $this->leftJoinSql.$this->whereSql.$this->groupBySql.$this->havingSql.$this->orderBySql;
            $this->sql = $str;
        }
        return $this->sql;
    }
}

Class Query {
    use Filter;
    private $db;
    public function __construct() {
        $this->db = DB::getInstance();
    }
    private function innerQuery() {
        //执行查询操作,如果执行成功返回true,如果执行错误返回的是false
        $this->getSql();
        $res = $this->db->query($this->sql);
        if(!$res) {
            die("查询错误:{$this->db->error},sql 语句是{$this->sql}");
        }
        return $res;
    }
    public function all() {
       $res = $this->innerQuery();
       $resArr = [];
       //把mysql对象转成结果并还条打印
       while($row = $res->fetch_assoc()) {
           $resArr[] = $row;
       }
       $res->free();
       return $resArr;
    }
    public function one() {
        $res = $this->innerQuery();
        $resArr = [];
        if($row = $res->fetch_assoc()){
            array_push($resArr, $row);
        }
        $res->free();
        return $resArr;
    }
}

class Operate{
    use Filter;
    private $db;
    public function __construct() {
        $this->db = DB::getInstance();
    }
    private function innerOperation() {
        $this->getSql();
        $res = $this->db->query($this->sql);
        if(!$res) {
            die(sprintf('执行失败,错误是%s, sql语句是%s', $this->db->error, $this->sql));
        }
        return $this->db->affected_rows;
    }
    public function execute() {
        return $this->innerOperation();
    }
}

//$subQuery = (new Query())->select('count(*) as num','classid')->from('class')->groupBy('deptname');
//$data = (new Query())->select('c.deptname','t.num')->from('class As c')
//    ->leftJoin(['t'=>$subQuery],'c.classid = t.classid')
//    ->where(['>=', 't.num',2])
//    ->getSql();
//$data = (new Operate())->update('student', ['name '=> 'haha ', 'age'=>30], 'studentid =   :id ', [':id'=> 26])->getSql();
//$data = (new Operate())->insert('student',['name'=>'bbb', 'age'=>30, 'classid' => 3])->getSql();
$data = (new Operate())->delete('student', ['name'=>'haha'])->execute();
var_dump($data);
?>

 

posted on 2019-05-12 16:21  even_blogs  阅读(372)  评论(0编辑  收藏  举报