<?php namespace Lib; use Model\listsSql; /** * db 查询 * @author:dc * @time 2023/2/13 15:03 * Class DbPool * @package Lib */ trait DbQuery { /** * @var \PDO|null */ protected $client; /** * 是否抛出异常 * @var bool */ protected $isThrow = false; /** * 是否缓存 * @var int */ protected int $cache = 0; /** * 没有数据时 也缓存 * @var bool */ protected bool $cacheNoData = true; public function getClient() { // 读取连接齐前 检查 // if(isset(static::$pool) && !$this->ping()){ // $this->close(); // $this->client = static::$pool->get(); // } return $this->client; } /** * @return $this * @author:dc * @time 2024/7/24 9:09 */ public function throw(){ $this->isThrow = true; return $this; } /** * 是否缓存结果 * @param int $ttl * @return $this * @author:dc * @time 2024/8/14 14:04 */ public function cache(int $ttl,bool $noData = true){ $this->cache = $ttl; $this->cacheNoData = $noData; return $this; } /** * 查询 * @param string|array $sql * @return false|\PDOStatement * @author:dc * @time 2023/2/17 10:01 */ public function query(string|array $sql){ if(is_array($sql)){ list($sql,$params) = $sql; }else{ $params = null; } if(APP_DEBUG) { $timer = microtime(true); } try { $query = $this->getClient()->prepare($sql); $ret = $query->execute($params); }catch (\Throwable $e){ if($this->isThrow){ $this->isThrow = false; throw new DbException($e->getMessage(),$sql,$params,$e); } logs([ $sql,$params, $e->getMessage(), $e->getTraceAsString() ], LOG_PATH.'/'.date('Y-m-d').'-sql.error.log' ); $ret = false; } $this->isThrow = false; if(APP_DEBUG){ $timer2 = microtime(true); // todo:: 记录日志,生产请注释 $sql = '['.substr(($timer2-$timer)*1000,0,6).'ms] '.$sql; logs( $params ? [$sql,$params] : $sql, LOG_PATH.'/'.date('Y-m-d').'.sql.log' ); } if($ret){ return $query; } return false; } /** * 更新数据 * @param string $table * @param array $data * @param string $where * @param bool $timeauto * @return int * @author:dc * @time 2023/2/17 14:03 */ public function update(string $table, array $data, string $where, $timeauto = true):int { if($timeauto){ $data['updated_at'] = empty($data['updated_at']) ? date('Y-m-d H:i:s') : $data['updated_at']; } // es 同步数据 \Event\Event::call('\Event\SyncMailToEs','update',$table,$where,$data); $sql = "update `{$table}` set ".dbUpdate($data). " where ".$where; $data = $this->getData($data); $query = $this->query([$sql,$data]); if($query){ return $query->rowCount(); } return 0; } /** * 在更新/插入时处理数据 * @param $data * @return mixed * @author:dc * @time 2023/2/18 14:50 */ public function getData($data){ // 如果存储的值是数组,就json一次 foreach ($data as $k=>$datum){ if(is_array($datum)){ $data[$k] = json_encode($datum,JSON_UNESCAPED_UNICODE); }elseif ($datum === null){ $data[$k] = ''; } } return $data; } /** * 插入数据 * @param string $table * @param array $data * @param bool $timeauto * @return int * @author:dc * @time 2023/2/17 14:04 */ public function insert(string $table, array $data, $timeauto = true):int { if($this->create($table, $data, $timeauto)){ return $this->getClient()->lastInsertId(); } return 0; } /** * 插入数据 * @param string $table * @param array $data * @param bool $timeauto * @return int * @author:dc * @time 2023/2/17 14:04 */ public function create(string $table, array $data, $timeauto = true):int { if($timeauto){ $data['created_at'] = empty($data['created_at']) ? date('Y-m-d H:i:s') : $data['created_at']; $data['updated_at'] = empty($data['updated_at']) ? date('Y-m-d H:i:s') : $data['updated_at']; } $sql = "insert into `{$table}` set ".dbUpdate($data); $data = $this->getData($data); $query = $this->query([$sql,$data]); if($query){ $data['id'] = $this->getClient()->lastInsertId(); // es 同步数据 \Event\Event::call('\Event\SyncMailToEs','create',$table, $data); return true; } return false; } /** * 删除语句 软删 * @param string $table * @param array $where * @param null $upFiled * @return int * @author:dc * @time 2023/4/11 14:47 */ public function delete(string $table, array $where,$upFiled=null){ if($upFiled){ return $this->update($table,[$upFiled === true ? 'deleted_at' : $upFiled =>time()],$where); } // es 同步数据 \Event\Event::call('\Event\SyncMailToEs','delete',$table, $where); $sql = "delete from `{$table}` where ".dbWhere($where); $query = $this->query($sql); if($query){ return $query->rowCount(); } return 0; } /** * 统计数量 * @param string $sql * @return int * @author:dc * @time 2023/2/14 16:19 */ public function count(string|array $sql):int{ return (int) $this->getCacheData($sql,0,\PDO::FETCH_COLUMN); } /** * 某个值 * @param string|array $sql * @return mixed|null * @author:dc * @time 2023/2/17 11:03 */ public function value(string|array $sql){ return $this->getCacheData($sql,null,\PDO::FETCH_COLUMN); $query = $this->query($sql); if($query){ return $query->fetch(\PDO::FETCH_COLUMN); } return null; } /** * 是否使用缓存 * @param $sql * @param string $default * @param null $flag * @return int|mixed|string * @throws DbException * @author:dc * @time 2024/9/23 11:57 */ private function getCacheData($sql, $default = '', $flag = null){ if($this->cache){ $key = 'data:'.md5(is_string($sql) ? $sql : json_encode($sql)); try { if(redis()->has($key)){ $this->cache = 0; $data = redis()->get($key,$default); if(!$this->cacheNoData){ if($data || $data === 0){ return $data; } } } }catch (\Throwable $e){ logs($e->getMessage()); } } $query = $this->query($sql); if($query){ $data = $flag? $query->fetch($flag) : $query->fetch(); if($this->cache){ try { redis()->set($key, $data, $this->cache); }catch (\Throwable $e){ logs($e->getMessage()); } $this->cache = 0; } return $data; } return $default; } /** * 查询一条数据 * @param string|array $sql * @return mixed|null * @author:dc * @time 2023/2/13 14:54 */ public function first(string|array $sql){ return $this->getCacheData($sql,[]); $query = $this->query($sql); if($query){ return $query->fetch(); } return null; } /** * 查询列表 * @param string|array $sql * @return mixed|null * @author:dc * @time 2023/2/13 14:54 */ public function all(string|array $sql){ if($this->cache){ try { $key = 'data:'.md5(is_string($sql) ? $sql : json_encode($sql)); if(redis()->has($key)){ $this->cache = 0; return redis()->get($key,[]); } }catch (\Throwable $e){ logs($e->getMessage()); } } $query = $this->query($sql); if($query){ $data = $query->fetchAll(); if($this->cache){ try { redis()->set($key,$data,$this->cache); }catch (\Throwable $e){ logs($e->getMessage()); } $this->cache = 0; } return $data; } return []; $query = $this->query($sql); if($query){ return $query->fetchAll(); } return []; } /** * 事务处理 * @param \Closure $call 闭包函数 返回true表示提交事务 返回false/抛出异常表示回滚事务 * @param mixed ...$params 传递给闭包函数的参数 * @author:dc * @time 2023/2/17 11:35 */ public function transaction(\Closure $call, ...$params){ $this->getClient()->beginTransaction(); try { if($call($this->getClient(),...$params)){ $this->getClient()->commit(); return true; } }catch (\Throwable $e){ } $this->getClient()->rollBack(); return false; } /** * 验证是否正常连接 * @return bool * @author:dc * @time 2024/4/10 10:09 */ public function ping(){ try { $query = $this->getClient()->query("select 200;"); if($query->fetchColumn() == 200){ return true; } }catch (\Throwable $e){ return false; } return false; } }