// +---------------------------------------------------------------------- use think\Collection; use think\db\exception\DbException; use think\exception\ClassNotFoundException; use think\Model; use think\Paginator; // 应用公共文件 if (!function_exists('widget')) { /** * 渲染输出Widget * @param string $name Widget名称 * @param array $data 传入的参数 * @return mixed * milo 2019-05-08 从TP5.1代码中拿来修改的 */ function widget($name, $data = []) { return action($name, $data, 'widget'); } } if (!function_exists('action')) { /** * 调用模块的操作方法 参数格式 [模块/控制器/]操作 * @param string $url 调用地址 * @param string|array $vars 调用参数 支持字符串和数组 * @param string $layer 要调用的控制层名称 * @param bool $appendSuffix 是否添加类名后缀 * @return mixed * milo 2019-05-08 从TP5.1代码中拿来修改的 */ function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) { $info = pathinfo($url); $action = $info['basename']; $module = '.' != $info['dirname'] ? $info['dirname'] : request()->controller(); $class = controller($module, $layer); if (is_scalar($vars)) { if (strpos($vars, '=')) { parse_str($vars, $vars); } else { $vars = [$vars]; } } return app()->invokeMethod([$class, $action . config('route.action_suffix')], $vars); } } if (!function_exists('controller')) { /** * 实例化(分层)控制器 格式:[模块名/]控制器名 * @access public * @param string $name 资源地址 * @param string $layer 控制层名称 * @param bool $appendSuffix 是否添加类名后缀 * @param string $empty 空控制器名称 * @return object * @throws ClassNotFoundException * * milo 2019-05-08 从TP5.1代码中拿来修改的 */ function controller($name, $layer = 'controller', $empty = '') { $class = parseClass($name, $layer); if (class_exists($class)) { return app()->make($class); } elseif ($empty && class_exists($emptyClass = app()->parseClass($layer, $empty))) { return app()->make($emptyClass); } throw new ClassNotFoundException('class not exists:' . $class, $class); } } if (!function_exists('parseClass')) { /** * 解析模块和类名 * @access protected * @param string $name 资源地址 * @param string $layer 验证层名称 * @param bool $appendSuffix 是否添加类名后缀 * @return array * * milo 2019-05-08 从TP5.1代码中拿来修改的 */ function parseClass($name, $layer) { if (false !== strpos($name, '\\')) { $class = $name; } else { if (strpos($name, '/')) { $names = explode('/', $name, 2); $name = $names[1]; } $class = app()->parseClass($layer, $name); } return $class; } } if (!function_exists('randomStr')) { /** * 获取随机字符串 * @param int $type 0:数字(默认);1:全部;2:小写字母;3:大写字母;4:字母; * @param int $len 字符串长度 * @return string */ function randomStr($type = 0, $len = 5) { $strPol = "0123456789"; if ($type == 1) { $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZ0123456789abcdefghijklmopqrstuvwyz"; } elseif ($type == 2) { $strPol = "abcdefghijklmopqrstuvwyz"; } elseif ($type == 3) { $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZ"; } elseif ($type == 4) { $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZabcdefghijklmopqrstuvwyz"; } $max = strlen($strPol) - 1; $str = ''; for ($i = 0; $i < $len; $i++) { $str .= $strPol[rand(0, $max)]; } return $str; } } if (!function_exists('isMobile')) { //判断访问终端是否为移动端 function isMobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) { return true; } // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息 if (isset($_SERVER['HTTP_VIA'])) { // 找不到为flase,否则为true return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false; } // 脑残法,判断手机发送的客户端标志,兼容性有待提高。其中'MicroMessenger'是电脑微信 if (isset($_SERVER['HTTP_USER_AGENT'])) { $clientkeywords = [ 'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu', 'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi', 'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile', 'MicroMessenger' ]; // 从HTTP_USER_AGENT中查找手机浏览器的关键字 if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) { return true; } } // 协议法,因为有可能不准确,放到最后判断 if (isset ($_SERVER['HTTP_ACCEPT'])) { // 如果只支持wml并且不支持html那一定是移动设备 // 如果支持wml和html但是wml在html之前则是移动设备 if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) { return true; } } return false; } } //根据栏目获取路径 if (!function_exists('getUri')) { function getUri($category) { if (!empty($category) && isset($category['id'])) { if (empty($category['route'])) { return '/page/' . $category['id'] . ".html"; } else { return $category['route']; } } return ''; } } //根据文件大小转换为文字 if (!function_exists('sizeToStr')) { function sizeToStr($size) { if (!is_numeric($size) || $size <= 0) { return ''; } $size = $size / 1024; if ($size < 1024) { return sprintf("%.2fK", $size); } $size = $size / 1024; if ($size < 1024) { return sprintf("%.2fM", $size); } $size = $size / 1024; return sprintf("%.2fG", $size); } } //根据路径获取文件名 if (!function_exists('getKeyByPath')) { function getKeyByPath($path) { return substr($path, strrpos($path, '/') + 1); } } //富文本中提取图片路径 if (!function_exists('getImageUrlFromText')) { function getImageUrlFromText($content) { preg_match_all('//is', $content, $imgs); $data = []; if (!empty($imgs) && !empty($imgs[1])) { foreach ($imgs[1] as $img) { if (substr($img, 0, 4) != 'http') { $key = getKeyByPath($img); $data[$key] = $img; } } } return $data; } } //富文本中提取视频路径 if (!function_exists('getVideoUrlFromText')) { function getVideoUrlFromText($content) { preg_match_all('//is', $content, $videos); $data = []; if (!empty($videos) && !empty($videos[1])) { foreach ($videos[1] as $video) { if (substr($video, 0, 4) != 'http') { $key = getKeyByPath($video); $data[$key] = $video; } } } return $data; } } //获取目录下的所有文件 if (!function_exists('getAllFilesByPath')) { function getAllFilesByPath($path, $rootPath) { if (is_dir($path) && file_exists($path)) { $items = scandir($path); $files = []; foreach ($items as $item) { if (substr($item, 0, 1) != '.' && strpos($item, '_') == false) { $itemPath = $path . '/' . $item; if (is_file($itemPath)) { $size = filesize($itemPath); $files[$item] = [ 'path' => str_replace($rootPath, '/', $itemPath), 'realPath' => $itemPath, 'size' => $size, 'sizeStr' => sizeToStr($size), 'suffix' => strtolower(substr($item, strrpos($item, '.') + 1)) //后缀 ]; } elseif (is_dir($itemPath)) { $childFiles = getAllFilesByPath($itemPath, $rootPath); if (!empty($childFiles)) { $files = array_merge($files, $childFiles); } else { rmdir($itemPath); } } } } return $files; } return []; } } //过滤get输入 if (!function_exists('getFilter')) { function getFilter($value) { $getFilter = "'|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; $forArray = false; if (is_array($value)) { $forFilter = implode($value); $forArray = true; } else { $forFilter = $value; } if (preg_match("/" . $getFilter . "/is", $forFilter) == 1) { $value = $forArray ? [] : ''; } return filterExp($value); } } //过滤post录入 if (!function_exists('postFilter')) { function postFilter($value) { $postFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; $forArray = false; if (is_array($value)) { $forFilter = implode($value); $forArray = true; } else { $forFilter = $value; } if (preg_match("/" . $postFilter . "/is", $forFilter) == 1) { $value = $forArray ? [] : ''; } return filterExp($value); } } //过滤cookie数据 if (!function_exists('cookieFilter')) { function cookieFilter($value) { $cookieFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; $forArray = false; if (is_array($value)) { $forFilter = implode($value); $forArray = true; } else { $forFilter = $value; } if (preg_match("/" . $cookieFilter . "/is", $forFilter) == 1) { $value = $forArray ? [] : ''; } return filterExp($value); } } if (!function_exists('filterExp')) { function filterExp($value) { $filter = '/^(\s)+(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)(\s)+$/i'; $forArray = false; if (is_array($value)) { $forFilter = implode($value); $forArray = true; } else { $forFilter = $value; } if (preg_match($filter, $forFilter) == 1) { $value = $forArray ? [] : ''; } return $value; } } if (!function_exists('arrayHtmlFilter')) { function arrayHtmlFilter($arr) { foreach ($arr as $k => $one) { if (is_array($one)) { $arr[$k] = arrayHtmlFilter($one); } else { $one = trim($one); $arr[$k] = strip_tags($one); } } return $arr; } } if (!function_exists('toCamelString')) { /** * 转驼峰 * * @param string $string * @param false $small 默认false 为true首字母小写 * @return string */ function toCamelString(string $string, bool $small = false): string { //例: xxx_yYy_zzZ 和 xxX-yyy-Zzz //1. 字符串转小写 xxx_yyy_zzz xxx-yyy-zzz //2. -和_转空格 xxx yyy zzz //3. 单词首字母大写 Xxx Yyy Zzz //4. 清除空格 XxxYyyZzz //处理下划线、减号 统统专程大驼峰 如xxx_yyy_zzz xxx-yyy-zzz 均转为 XxxYyyZzz $string = strtolower($string); $string = str_replace('-', ' ', $string); $string = str_replace('_', ' ', $string); $string = str_replace(' ', '', ucwords($string)); if ($small) { $string = lcfirst($string); } return $string; } } if (!function_exists('unCamelize')) { /** * 驼峰命名转特定分隔符[如下划线]命名 * @param string $camelCaps * @param string $separator * @return string */ function unCamelize(string $camelCaps, string $separator = '-'): string { return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps)); } } if (!function_exists('generateRand')) { /** * 生成随机数 * * @param int $length 长度 * @param string $type 模式 默认mix混合 number纯数字 alpha字母 * @return string */ function generateRand(int $length = 8, string $type = 'mix'): string { $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $number = '0123456789'; $alphabetLen = strlen($alphabet) - 1; $numberLen = 9; switch ($type) { case 'number': $str = $number; $len = $numberLen; break; case 'alpha': $str = $alphabet; $len = $alphabetLen; break; default: $str = $alphabet . $number; $len = $alphabetLen + $numberLen; } $randStr = ''; $str = str_shuffle($str); for ($i = 0; $i < $length; $i++) { $num = mt_rand(0, $len); $randStr .= $str[$num]; } return $randStr; } } if (!function_exists('generateCode')) { /** * 生成特定编码 * * @param string $type 类型 默认mix混合 number纯数字 alpha字母 * @param int $len 随机数长度 * @return string */ function generateCode(string $type = 'number', int $len = 6): string { //#时间戳+微秒+6位随机数 $time = microtime(true); $timeStr = str_replace('.', '', $time); return sprintf("%s%s", $timeStr, generateRand($len, $type)); } } if (!function_exists('checkMobile')) { /** * 检测手机号 * * @param string $mobile * @return bool */ function checkMobile(string $mobile): bool { if (preg_match("/^1[3456789]{1}\d{9}$/", $mobile)) { return true; } else { return false; } } } if (!function_exists('arrayKeysFilter')) { /** * 数组键名过滤 * * @param array $data * @param array $allowKeys * @return array */ function arrayKeysFilter(array $data, array $allowKeys): array { $list = []; foreach ($data as $key => $val) { if (in_array($key, $allowKeys)) { $list[$key] = $val; } } return $list; } } if (!function_exists('getFilesize')) { /** * 尺寸单位转换 * * @param $num * @return string */ function getFilesize($num): string { $p = 0; $format = 'B'; if ($num > 0 && $num < 1024) { return number_format($num) . ' ' . $format; } if ($num >= 1024 && $num < pow(1024, 2)) { $p = 1; $format = 'KB'; } if ($num >= pow(1024, 2) && $num < pow(1024, 3)) { $p = 2; $format = 'MB'; } if ($num >= pow(1024, 3) && $num < pow(1024, 4)) { $p = 3; $format = 'GB'; } if ($num >= pow(1024, 4) && $num < pow(1024, 5)) { $p = 3; $format = 'TB'; } $num /= pow(1024, $p); return number_format($num, 3) . ' ' . $format; } } if (!function_exists('arrayNullToString')) { /** * 数组|或数据集中null值转为空字符串,并以数组格式返回 * 通常用于api json 返回内容null转换 * * @param array $data 【array|collection】 * @return array */ function arrayNullToString($data) { if ($data instanceof Collection || $data instanceof Model) { $data = $data->toArray(); } // 判断是否可以遍历 if (is_iterable($data)) { foreach ($data as $key => $val) { if ($val instanceof Collection || $data instanceof Model) { $val = $val->toArray(); } if (is_iterable($val)) { $data[$key] = arrayNullToString($val); } elseif ($val === null) { $data[$key] = ''; } } } else { $data = []; } return $data; } } if (!function_exists('arrayKeysExcludeFilter')) { /** * 数组键名排除过滤 * * @param array $data * @param array $excludeKeys 排除的字段 * @return array */ function arrayKeysExcludeFilter(array $data, array $excludeKeys): array { foreach ($data as $key => $val) { if (in_array($key, $excludeKeys)) { unset($data[$key]); } } return $data; } } if (!function_exists('getLatelyWeekDate')) { /** * 获取本周的周一 到周日的日期 */ function getLatelyWeekDate() { //本周一 $oneDate = date('Y-m-d 00:00:00', (time() - ((date('w') == 0 ? 7 : date('w')) - 1) * 86400)); //w为星期几的数字形式,这里0为周日 $oneDateTime = strtotime($oneDate); //返回周一到周天 1-7 return [ "1" => ["date"=>$oneDate], "2" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 1)))], "3" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 2)))], "4" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 3)))], "5" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 4)))], "6" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 5)))], "7" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 6)))], ]; } } if (!function_exists('stringDesensitization')) { /** * 字符串脱敏 默认给手机号脱敏 其他未兼容 * * @param string $string * @param string $s * @param int $start * @param int $len * @return string */ function stringDesensitization(string $string, string $s = '****', int $start = 3, int $len = 4): string { return substr_replace($string, $s, $start, $len); } } if (!function_exists('checkPathExistWithMake')) { /** * 检测文件夹是否存在,不存在时自动创建(需要有写入权限) * 支持递归创建 * * @param string $absolutePath * @return bool */ function checkPathExistWithMake(string $absolutePath): bool { try { $absolutePath = rtrim($absolutePath, '/'); if (empty($absolutePath)) { return false; } if (!is_dir($absolutePath)) { return mkdir($absolutePath, 0777, true); } return true; } catch (\Exception $e) { return false; } } }