* [ ] CurdTrait.php * [ ] 功能 * 简单的封装CURD操作,在项目里面操作数据库表的 Model 层里面 use CurdTrait * 把常用的功能简单封装,方便维护,当底层框架 mysql 操作类方法改变的时候,只需要修改该文件即可 * 文件路径:/home/wwwroot/project/application/lib/model/Common/CurdTrait.php ~~~ <?php namespace model\Common; /** * Trait CurdTrait * 针对数据库的 CURD 操作,增、删、改、查 * 用法:在需要的 Model 中 use CurdTrait; * 并且这个 Model 中必须定义静态成员变量: * 假设 model 文件为 UserModel * 如果在 UserModel 中定义的成员变量 $tabName 为空,那么该 trait 会自动获取当前类名,去截取到 user 表名 * 同理 UserLogModel,如果定义的成员变量 $tabName 为空,那么该 trait 会自动获取当前类名,去截取到 user_log 表名 * 例如: * protected static $dbObj = 'Admin'; //操作的数据库 * protected static $tabName = 'admin'; //操作的表名 * protected static $tabId = 'id'; //[如果没有,就不需要定义] 该表的主键 * @package model\Common * @author YoY */ trait CurdTrait { //当前model操作的表对象 protected static $tabObj = false; /** * 下划线转驼峰 * @param string $str * @return string|string[]|null * @author YoY */ public static function lineToHump($str = '') { if (empty($str)) { return ''; } $str = preg_replace_callback('/([-_]+([a-z]{1}))/i', function ($matches) { return strtoupper($matches[2]); }, $str); return empty($str) ? '' : $str; } /** * 驼峰转下划线 * @param string $str * @return string|string[]|null * @author YoY */ public static function humpToLine($str = '') { if (empty($str)) { return ''; } $str = preg_replace_callback('/([A-Z]{1})/', function ($matches) { return '_' . strtolower($matches[0]); }, $str); $str = ltrim($str, '_'); return empty($str) ? '' : $str; } /** * 记录允许日志,比如允许中遇到的异常 * @param $message * @return bool * @author YoY */ public static function runLog($message) { try { //如果 seaslog 拓展没有安装,就不记录异常日志了 if (!extension_loaded('seaslog')) { return false; } if (is_array($message) || is_object($message)) { $message = json_encode($message, JSON_UNESCAPED_UNICODE); } return \SeasLog::info($message); } catch (\Exception $e) { return false; } } /** * 获取操作的表名 * @return string * @author YoY */ public static function getTabName() { // 如果定义的操作的表名为空,默认根据当前类文件名称去截取 TaskModel 自动找到task表名 if (empty(self::$tabName)) { $_class_ = explode('\\', __CLASS__); $key = count($_class_) - 1; $_class_ = self::humpToLine($_class_[$key]); $_class_ = explode('_', $_class_); $key = count($_class_) - 1; if ($key > 0) unset($_class_[$key]); self::$tabName = implode('_', $_class_); } return self::$tabName; } /** * 获取表主键 * @return string * @author YoY */ public static function getTabId() { // 默认主键 if (!isset(self::$tabId)) self::$tabId = 'id'; return self::$tabId; } /** * 获取操作表对象 * @return bool * @throws \Exception * @author YoY */ public static function getTabOBJ() { if (!isset(self::$dbObj)) throw new \Exception('操作表数据库对象 self::$dbObj 未定义'); self::getTabName(); if (!isset(self::$tabName)) throw new \Exception('操作表名 self::$tabName 未定义'); if (empty(self::$tabObj) || !is_object(self::$tabObj) || empty(self::$tabObj->MyData['table'])) { $dbObj = '\\mysql\\' . self::$dbObj; //拼接操作表对象的静态类 self::$tabObj = $dbObj::table(self::$tabName); } return self::$tabObj; } /** * 添加记录 * 例如:user表新增一条记录 name = YoY pwd = 123456 的记录到表中 * 返回添加成功的主键:UserModel::add( ['name' => 'YoY', 'pwd' => 123456] ); * 返回添加成功的影响行数:UserModel::add( ['name' => 'YoY', 'pwd' => 123456], 'row' ); * 如果只是需要返回sql语句:UserModel::add( ['name' => 'YoY', 'pwd' => 123456], 'demo' ); * @param array $data [要新增的数据] * @param string $get_sql [返回的形式] * @return bool * @author YoY */ public static function add($data = [], $get_sql = '') { if (empty($data) || !is_array($data)) { return false; } try { // 如果没有定义主键,那么就只能返回影响的行数 if (!isset(self::$tabId) && empty($get_sql)) $get_sql = 'row'; return self::getTabOBJ()->data($data)->insert($get_sql); } catch (\Exception $e) { // 记录异常日志 self::runLog($e->getMessage()); return false; } } /** * 批量添加记录 * 例如:user表批量添加记录 name = 1, pwd = 123 和 name = 2, pwd = 321 的记录 * 用法1:UserModel::addAll( [ ['name'=>1, 'pwd' => 123], [ 'name' => 2, 'pwd' => 321] ] ); * 需要返回sql语句:UserModel::addAll( [ ['name'=>1, 'pwd' => 123], [ 'name' => 2, 'pwd' => 321] ], 'demo' ); * @param array $data * @param string $get_sql * @return bool * @author YoY */ public static function addAll($data = [], $get_sql = '') { if (empty($data)) { return false; } if (empty(self::$tabId) && empty($get_sql)) { $get_sql = 'row'; } try { return self::getTabOBJ()->data($data)->add($get_sql); } catch (\Exception $e) { // 记录异常日志 self::runLog($e->getMessage()); return false; } } /** * 删除记录 * 例如:user表删除一个id为1的记录 * 用法1:UserModel::delete( 1 ); * 用法2:UserModel::delete( '1' ); * 用法3:UserModel::delete( ['id' => 1] ); * 用法4:UserModel::delete( ['id' => '1'] ); * 如果只是返回sql语句:UserModel::delete( ['id' => 1], 'demo' ); * @param array $where [删除记录的where条件] * @param string $get_sql [是否只返回sql语句,如果写入demo,就是返回sql语句] * @return bool * @author YoY */ public static function delete($where = [], $get_sql = '') { if (!is_array($where) && !is_string($where) && !is_int($where)) { return false; } if (is_array($where) && empty($where)) { return false; } if (is_string($where) && empty($where) && $where !== '0') { return false; } // 不是一个数组,那么就是想通过主键去删除 if (!is_array($where)) { $where = intval($where); // 如果不存在主键定义,或者定义了却为空,就返回失败 if (empty(self::getTabId())) { return false; } // 存在主键定义,就自动组装主键的where条件 $where = [self::getTabId() => $where]; } try { return self::getTabOBJ()->where($where)->delete($get_sql); } catch (\Exception $e) { // 记录异常日志 self::runLog($e->getMessage()); return false; } } /** * 修改记录 * 例如:user表修改id字段为1的记录中的name为new name * 用法1:UserMode::save( 1, ['name' => 'new name'] ); * 用法2:UserModel::save( '1', ['name' => 'new name'] ); * 用法3:UserModel::save( ['id' => 1], ['name' => 'new name'] ); * 用法4:UserModel::save( ['id' => '1'], ['name' => 'new name'] ); * 用法5:UserModel::save( ['id' => 1, 'name' => 'new name'] ); * 用法6:UserModel::save( ['id' => '1', 'name' => 'new name'] ); * 如果只是返回sql语句:UserModel::save( ['id' => 1], ['name' => 'new name'], 'demo' ); * @param array $where [要修改的where条件 ] * @param array $data [要修改新的数据值] * @param string $get_sql [是否只返回sql语句,如果写入demo,就是返回sql语句] * @return bool * @author YoY */ public static function save($where = [], $data = [], $get_sql = '') { if (!is_array($where) && !is_string($where) && !is_int($where)) { return false; } if (is_array($where) && empty($where)) { return false; } if (is_string($where) && empty($where) && $where !== '0') { return false; } if (!is_array($where)) { // 如果传入的where条件是以主键,那么就组装主键条件 // 对应使用场景: $tabObj->save( 1, ['name'=>'new name'] ); // 对应使用场景: $tabObj->save( '0', ['name'=>'new name'] ); // 防止有些表的主键是有0存在的时候 $where = intval($where); if (empty(self::getTabId())) { return false; } $where = [self::getTabId() => $where]; } else { // 如果传入的是where条件,且where条件中含有主键,并且data是空 // 对应使用场景: $tabObj->save( ['id'=>1,'name'=>'new name'] ); if (is_array($where) && empty($data)) { // 如果是想按照主键来更新,但是又没有定义主键名称或者定义的主键名称为空 if (empty(self::getTabId())) { return false; } // 然后更新的数据里面,主键字段不存在 if (!isset($where[self::getTabId()])) { return false; } $data = $where; $where = [self::getTabId() => $where[self::getTabId()]]; unset($data[self::getTabId()]); } } // 防止where条件或更新的数据都为空 if (empty($where) || empty($data)) { return false; } try { return self::getTabOBJ()->where($where)->data($data)->update($get_sql); } catch (\Exception $e) { // 记录异常日志 self::runLog($e->getMessage()); return false; } } /** * 根据where条件查询单条数据 * 例如:user表获取一条ID为1的记录的name、pwd字段的值 * 用法1:UserModel::find( 1, 'name,pwd' ); * 用法2:UserModel::find( '1', 'name,pwd' ); * 用法3:UserModel::find( ['id' => 1], 'name,pwd' ); * 用法4:UserModel::find( ['id' => '1'], 'name,pwd' ); * 如果只是返回sql语句:$tabObj->find( ['id' => '1'], 'name,pwd', [], 'demo' ); * @param array $where * @param string $field * @param $other array [ 其他属性, 比如排序order] * @param string $get_sql [是否只返回sql语句,如果写入demo,就是返回sql语句] * @return array * @author YoY */ public static function find($where = [], $field = '', $other = [], $get_sql = '') { if (!is_string($field)) { return []; } // 排序规则 $order = $other['order'] ?? ''; $order = self::data_format_order($order); // 如果where条件不是数组,那么就是想通过主键来查询 if (!is_array($where)) { // 想通过主键查询,可是又没有设置主键名称,那么就返回空数组 if (empty(self::getTabId())) { return []; } // 主键查询 $where = [self::getTabId() => intval($where)]; } try { return self::getTabOBJ()->where($where)->field($field)->order($order)->find($get_sql); } catch (\Exception $e) { // 记录异常日志 self::runLog($e->getMessage()); return []; } } /** * 根据where条件查询数据 * 例如:user表获取 state 为 1的 所有记录,只要字段 id,name,pwd,state,并且按照 id降序,state降序 * 用法1:UserModel::select( ['state' => 1], 'id,name,pwd,state','id DESC,state DESC') * 用法2:UserModel::select( ['state' => 1], 'id,name,pwd,state','id DESC,state DESC') * @param array $where [查询的where条件] * @param string $field * @param string $order * @param array $other [ 这个是其他附加属性,比如限制查询的条数,limit,默认limit是查询所有] * @param string $get_sql [是否只返回sql语句,如果写入demo,就是返回sql语句] * @return array * @author YoY */ public static function select($where = [], $field = '', $order = '', $other = [], $get_sql = '') { // 如果排序为空,默认以主键降序来排序 if (empty($order)) { $order = empty(self::getTabId()) ? '' : self::getTabId() . ' DESC'; } // 如果排序为数组,那么需要拼接为字符串 ['id' => 'DESC', 'state' => 'ASC'] 转为 'id DESC,state ASC' $order = self::data_format_order($order); // 限制数量 $limit = $other['limit'] ?? 'all'; // 分组 $group = $other['group'] ?? ''; //针对字段查询的时候,可能需要某个字段作为数组的key返回 $fieldBox = explode('|', $field); $field_key = ''; if (count($fieldBox) > 1) { $field = $fieldBox[0]; $field_key = $fieldBox[1]; } try { $tabObj = self::getTabOBJ()->where($where)->order($order)->field($field, $field_key); // 判断是否为查询所有,如果不是查询所有,那么就增加一个连贯操作limit,限制查询的数量 if ($limit !== 'all') { $tabObj = $tabObj->limit($limit); } if (!empty($group)) { $tabObj = $tabObj->group($group); } return $tabObj->select($get_sql); } catch (\Exception $e) { // 记录异常日志 self::runLog($e->getMessage()); print_r($e->getMessage()); return []; } } /** * 分页查询数据 * @param int $page [ 页码 ] * @param int $num [ 每页总条数 ] * @param array $other [ 其他属性,比如 查询条件where(array), 排序order(array or string), 返回字段field(string) ] * @return array * @author YoY */ public static function getPage($page = 1, $num = 50, $other = []) { $where = $other['where'] ?? []; $order = $other['order'] ?? ''; $field = $other['field'] ?? ''; // 整理排序 $order = self::data_format_order($order); try { $data = self::getTabOBJ()->where($where)->order($order)->field($field)->page($num, $page); } catch (\Exception $e) { $data = array( 'page' => array( 'total' => 0, 'pages' => 0, 'top' => 0, 'next' => 0, 'page' => $page, 'count' => $num, 'head' => 0, ), 'list' => [], ); } return $data; } /** * 统计数量 * @param $where * @param string $field * @param array $other * @return int */ public static function count( $where, $field = '*', $other = []) { $mode = $other['mode'] ?? ''; $type = $other['type'] ?? ''; $come = $other['come'] ?? ''; try{ return self::getTabOBJ()->where($where)->count($field, $mode, $type, $come); }catch ( \Exception $e ){ return 0; } } /** * 整理排序 * @param string $order * @return string * @author YoY */ protected static function data_format_order($order = '') { if (!empty($order) && is_array($order)) { $tmp_order = []; //如果是数组,组装为字符串 foreach ($order as $field_name => $field_val) $tmp_order[] = $field_name . ' ' . $field_val; $order = implode(',', $tmp_order); } return $order; } /** * 复制表结构 * @param $table * @param string $newtable * @return bool */ public static function creste($table, $newtable = '') { try{ $dbObj = '\\mysql\\' . self::$dbObj; return $dbObj::creste($table, $newtable); } catch ( \Exception $e ) { return false; } } /** * 开始事务 * @return bool */ public static function beg() { try { $dbObj = '\\mysql\\' . self::$dbObj; $dbObj::beg(); return true; } catch (\Exception $e) { return false; } } /** * 提交事务 * @return bool */ public static function com() { try { $dbObj = '\\mysql\\' . self::$dbObj; $dbObj::com(); return true; } catch (\Exception $e) { return false; } } /** * 事务回滚 * @return bool */ public static function rol() { try { $dbObj = '\\mysql\\' . self::$dbObj; $dbObj::rol(); return true; } catch (\Exception $e) { return false; } } /** * 获取操作的类对象 * @return string */ protected static function getDbOBJ() { //拼接操作表对象的静态类 return '\\mysql\\'.self::$dbObj; } /** * 判断数据库的某个表是否存在 * @param $table * @return bool */ public static function mysql_if_table($table) { try { return (self::getDbOBJ())::mysql_if_table($table); } catch ( \Exception $e ) { return false; } } /** * @param $data * @param string $field * @return bool */ protected static function tabname($data, $field = '') { try { return (self::getDbOBJ())::tabname($data, $field); } catch ( \Exception $e ) { return false; } } /** * 联合表 * @param $data * @param bool $type * @return bool */ protected static function union($data, $type = false) { try { return (self::getDbOBJ())::union($data, $type); } catch ( \Exception $e ) { return false; } } } ~~~