$type(json_encode($data, JSON_UNESCAPED_UNICODE)); } /** * 字段映射 * * @param array $data * @param array $map * @param array $options * @return array * @date 2022-06-23 * @example * @author arw * @since 1.0.0 */ public static function fieldMap(array $data, array $map, array $options = []): array { $prefix = Arr::get($options, 'prefix', ''); $result = []; foreach ($data as $key => $value) { if (isset($map[$key])) { $key = $map[$key]; } if ($prefix) { $key = $prefix . $key; } $result[$key] = $value; } return $result; } /** * 转换日期格式 * * @param string $datetime * @param string $format * @return string * @date 2022-04-20 * @example * @author arw * @since 1.0.0 */ public static function conversionDateTime($datetime, string $format): string { try { $date = new DateTime($datetime); return $date->format($format); } catch (\Throwable $th) { throw new ErrorMsg('日期格式非法', 1); } } /** * 生成唯一id * * @param string|array $value * @return string * @date 2022-03-24 * @example * @author arw * @since 1.0.0 */ public static function generateGuid($value = ''): string { $str = ''; if (is_array($value)) { $str = json_encode($value); } $charid = strtolower(md5($str . uniqid('', true))); $hyphen = chr(45); // '-' $uuid = //chr(123)// '{' substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12); //.chr(125);// '}' return $uuid; } /** * 清空(擦除)缓冲区并关闭输出缓冲 * * @return void */ public static function obEndClean(): void { try { while (ob_get_level() > 0) { ob_end_clean(); } } catch (\Throwable $th) { //throw $th; } } /** * 自动创建文件夹 * * @param string $path 文件夹路径 * @param integer $mode 权限 * @return boolean */ public static function mkdir(string $path, int $mode = 0755): bool { $path = str_replace('/', DIRECTORY_SEPARATOR, $path); $temp = explode(DIRECTORY_SEPARATOR, $path); if (preg_match("/\./", end($temp))) { // pathinfo 不支持中文 // $path = pathinfo($path, PATHINFO_DIRNAME); array_splice($temp, count($temp) - 1, 1); $path = join(DIRECTORY_SEPARATOR, $temp); } if (!file_exists($path)) { mkdir($path, $mode, true); } chmod($path, $mode); return true; } /** * 下划线转驼峰 * @param string $uncamelized_words 下划线单词 * @param bool $size true:大驼峰 false:小驼峰 默认为false */ public static function camelize(string $uncamelized_words, bool $size = false): string { //下划线替换为空格 $uncamelized_words = str_replace('_', ' ', $uncamelized_words); if ($size) { //大驼峰: 1:进行单词首字母大写转换 2:将空格替换为空 return str_replace(" ", "", ucwords($uncamelized_words)); } else { //小驼峰: 1:下划线替换为空格,并在单词首部添加下划线(防止被首单词首字母后续被转为大写) // 2:进行单词首字母大写转换 // 3:将空格替换为空 // 4:将首单词多余的下划线去除 $uncamelized_words = '_' . $uncamelized_words; return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), '_'); } } /** * 驼峰命名转下划线命名 * @param string $uncamelize 驼峰单词 */ public static function uncamelize($camelCaps): string { return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . '_' . "$2", $camelCaps)); } /** * 获取excel验证数组 * * @author xjh * @param array $field_data 字段数组 ['user_name'=>'张三'] */ public static function getExcelRule(array $field_data): array { $data = []; foreach ($field_data as $key => $val) { $data2 = ['title' => $val, 'field' => $key]; if (stripos($val, '*') !== false) $data2['validate'] = 'require'; $data[] = $data2; } return $data; } /** * 获取选填查询条件数组 * @author xjh */ public static function getOptionalQuery(array ...$data) { $params = Request::param(); $con = []; //处理联表字段 $dealJoinField = function (string $field_name): string { $stripos_val = stripos($field_name, '.'); return $stripos_val !== false ? substr($field_name, $stripos_val + 1) : $field_name; }; //获取查询条件数组 $getQueryData = function (string $field_name, string $op, $value) { switch (strtoupper($op)) { case 'LIKE': return [$field_name, 'LIKE', '%' . $value . '%']; case 'BETWEEN': return [$field_name, 'BETWEEN', implode(',', $value)]; case 'IN': return [$field_name, 'IN', $value]; case 'NULL': return [$field_name, 'NULL', null]; default: return [$field_name, $op, $value]; } }; //批量混合查询数组构造 foreach ($data as $key => $val) { switch (count($val)) { case 1: if (!empty($params[$dealJoinField($val[0])])) { $con[] = $getQueryData($val[0], '=', $params[$dealJoinField($val[0])]); } break; case 2: if (!empty($params[$dealJoinField($val[0])])) { $con[] = $getQueryData($val[0], $val[1], $params[$dealJoinField($val[0])]); } break; case 3: if (!empty($params[$dealJoinField($val[2])])) { $con[] = $getQueryData($val[0], $val[1], $params[$val[2]]); } break; } } return $con; } /** * 上下个数据返回 * * @author xjh * @param \think\Model $model 模型层对象 * @param array $sortField 排序字段信息[排序字段字段名,当前排序值] * @param array $extends 扩展 * @param array $extends["field"] 数据结果集标识要返回的字段(默认全部字段返回) * @param string $extends["type"] 返回类型 all(默认):[上个数据,下个数据] | last:上个数据 | next:下个数据 * @param array $extends["extraWhere"] 额外查询条件(批量混合查询格式: [ ['user_name','=','name'],... ]) * @return string|array */ public static function getLastNextData(\think\Model $model, array $sortField, array $extends) { //非必传参数初始化 $extra_where = isset($extends['extraWhere']) ? $extends['extraWhere'] : []; $field = isset($extends['field']) ? $extends['field'] : null; $type = isset($extends['type']) ? $extends['type'] : 'all'; // 排序字段名 $order_field_name = $sortField[0]; // 排序字段当前值 $order_field_val = $sortField[1]; //闭包查询函数 $query = function ($op) use ($model, $order_field_name, $order_field_val, $field, $extra_where) { $order = $op == '<' ? 'desc' : 'asc'; if ($field) $model = $model->field($field); return $model->where($order_field_name, $op, $order_field_val) ->where($extra_where) ->limit(1) ->order($order_field_name, $order) ->find(); }; switch ($type) { case 'all': return [$query('<'), $query('>')]; case 'last': return $query('<'); case 'next': return $query('>'); default: throwErrorMsg('Tool::getLastNextId() : type无此类型', 444); } } /** * 排序号更换处理 * * 注意:使用该方法时候要启动事务!! * @param string $model 模型层命名空间地址 * @param string $guid 主键 * @param int $order 新排序号 * @param array $extra_wheres 当前指定数据的额外查询条件(tp批量查询数组) 例:["xxx_type" => 1,...] */ public static function sortEditProc(string $model, string $guid, int $order, array $extra_wheres = []): void { //模型层实例化 $model = new $model; //表名 $table_name = $model->db()->getTable(); //获取当前的主键字段名 $guld_field = $model->db()->getPk(); //排序字段名 if (!isset($model->order_field)) throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field'); $order_field_name = $model->order_field; //当前数据原信息 $original_oreder_find = $model->where($guld_field, $guid)->find(); if (!$original_oreder_find) throwErrorMsg('Tool::sortEditProc() : 找不到该数据原排序号', 444); //查找当前数据所想更换的新排序号是否已有数据占用(排除自己) //已被占用,则将它们的排序号互换 if ($model->where($order_field_name, $order)->where($guld_field, '<>', $guid)->where($extra_wheres)->find()) { $update_data = [$order_field_name => $original_oreder_find[$order_field_name]]; if (isset($model->parent_guid_field)) { $update_data[$model->parent_guid_field] = $original_oreder_find[$model->parent_guid_field]; } if (isset($model->ancestors_guid_field)) { $update_data[$model->ancestors_guid_field] = $original_oreder_find[$model->ancestors_guid_field]; } Db::name($table_name)->where($order_field_name, $order)->where($extra_wheres)->update($update_data); } } /** * 排序号腾位处理 * * 注意:使用该方法时候要启动事务!! * @param string $model 模型层命名空间地址 * @param int $order 当前排序号 * @param array $wheres 当前指定数据的额外查询条件(tp批量查询数组) 例:["xxx_type" => 1,...] */ public static function sortInsertProc(string $model, int $order, array $wheres = []): void { //模型层实例化 $model = new $model; //表名 $table_name = $model->db()->getTable(); //排序字段名 if (!isset($model->order_field)) throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field'); $order_field_name = $model->order_field; //新增数据的所属排序号已有数据占用,则腾位处理(已占用的数据及其后面所有数据一起排序号腾位+1) if ($model->where($order_field_name, $order)->where($wheres)->value($order_field_name) !== null) { Db::name($table_name) ->where($wheres) ->where($order_field_name, '>=', $order) ->inc($order_field_name) ->update(); } } /** * 排序号删除处理 * 注意:使用该方法时候要启动事务!! * @param string $model 模型层命名空间地址 * @param array $guid 主键 * @param array $correl_fields 关联字段 例:["xxx_guid",...] 代表删除排序号时会根据这些字段来关联(例:所属xxx类型、所属xxx系列)来进行排序处理 */ public static function sortDeleteProc(string $model, string $guid, array $correl_fields = []): void { //模型层实例化 $model = new $model; //获取当前的主键字段名 $guld_field_name = $model->db()->getPk(); //获取当前表排序字段名 if (!isset($model->order_field)) throwErrorMsg('排序处理失败!模型层未定义排序字段$order_field'); $order_field_name = $model->order_field; //在所删除的数据之后的数据所属排序号将进行减位处理减位-1 if ($find = $model->where($guld_field_name, $guid)->find()) { $con = []; foreach ($correl_fields as $correl_field) { $con[$correl_field] = $find[$correl_field]; } $model->where($order_field_name, '>', $find[$order_field_name]) ->where($con) ->dec($order_field_name) ->save(); } } /** * 处理(树形数据父子)伦理关系 * * @param \think\Model $model 模型层对象 */ public static function handleEthicalRel(\think\Model $model): void { if (!isset($model->parent_guid_field) || !isset($model->ancestors_guid_field)) { throwErrorMsg(__METHOD__ . "方法:" . get_class($model) . "模型层必须定义public \$parent_guid_field,public \$works_type_ancestors_guid"); } //获取当前的主键字段名 $guld_field = $model->db()->getPk(); //当前父级主键字段名 $parent_guid_field = $model->parent_guid_field; //当前祖级级主键字段名 $ancestors_guid_field = $model->ancestors_guid_field; //处理一 if ($model[$guld_field] == $model[$parent_guid_field]) { throwErrorMsg("不可以当自己的子级!"); } //处理二 $is_children = $model->where([ [$guld_field, '=', $model[$parent_guid_field]], [$ancestors_guid_field, 'REGEXP', $model[$guld_field]], ])->find(); if ($is_children) { throwErrorMsg("不可以当自己孩子们的子级!"); } } /** * 祖级guid构建 * @param \think\Model $model 模型层命名空间地址 * @param bool $is_unipolar 是否为单极结构 */ public static function buildAncestorsGuid(\think\Model &$model, bool $is_unipolar = false): void { //获取最大父级guid $first_parent_guid = isset($model->first_parent_guid) ? $model->first_parent_guid : "0"; //获取当前的主键字段名 $guld_field_name = $model->db()->getPk(); //获取当前父级主键集字段名 $parent_guid_field = $model->parent_guid_field; $parent_guid = $model[$parent_guid_field]; //获取当前祖级主键集字段名 $ancestors_guid_field = $model->ancestors_guid_field; //单极结构或父级guid已经为最大父级guid时直接返回最大父级guid if ($is_unipolar || $parent_guid == $first_parent_guid) { $model[$ancestors_guid_field] = $first_parent_guid; return; } //开始构建祖级guid $parent = $model->where($guld_field_name, $parent_guid)->find(); if (!$parent) throwErrorMsg('该父级数据不存在!'); $model[$ancestors_guid_field] = $parent[$ancestors_guid_field] . ',' . $parent_guid; } /** * 初始化模型字段值 * * @param \think\Model &$model 模型层对象(引用传递) * @param array $field_values 初始化字段信息 例: ['user_name'=>'张三',...] */ public static function initModelFieldValue(\think\Model &$model, array $field_values): void { foreach ($field_values as $field => $value) { $model[$field] = $value; } } }