<?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); ?>