侧边栏壁纸
博主头像
云BLOG 博主等级

行动起来,活在当下

  • 累计撰写 318 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

THINKPHP8增强的基本控制器

Administrator
2025-10-22 / 0 评论 / 0 点赞 / 1 阅读 / 0 字
<?php
namespace app\common\business\lib;

use app\BaseController;
use think\facade\Db;
use think\facade\Validate;
use think\facade\Request;
use think\exception\ValidateException;
use think\exception\DbException;

/**
 * 增强版基础控制器 - BaseMethod
 * 
 * 整合原有BaseMethod所有功能,并添加增强方法
 * 功能特性:
 * 1. 保留所有原有数据库操作方法
 * 2. 添加统一的API响应格式
 * 3. 增强数据验证和参数处理
 * 4. 提供丰富的工具方法
 * 5. 支持操作日志记录
 * 6. 完整兼容ThinkPHP8原生功能
 * 
 * 使用示例:
 * class Product extends BaseMethod
 * {
 *     public function index()
 *     {
 *         // 使用原有方法
 *         $list = $this->Retrieve('product', 'status', 1);
 *         
 *         // 使用新增方法
 *         $pagedList = $this->newGetList('product', ['status' => 1], ['*'], 'id DESC', [], true);
 *         
 *         return $this->newSuccess($pagedList);
 *     }
 * }
 */
class BaseMethod extends BaseController
{
    /**
     * 字段映射表(可被子类覆盖)
     */
    protected $fieldMap = [
        'username' => '用户名',
        'email'    => '邮箱',
        'password' => '密码',
        'id_card'  => '身份证号码',
        'mobile'   => '手机号',
        'age'      => '年龄',
    ];

    /**
     * 每页显示数量
     */
    protected $pageSize = 20;

    /******************************************************************
     *                       原有BaseMethod方法
     *             保持完全兼容,不做任何修改
     ******************************************************************/

    /**
     * 快速验证方法(支持字符串或数组规则)
     *
     * @param array $data 需要验证的数据
     * @param array|string $rules 验证规则(字符串格式或数组)
     * @param array $messages 自定义错误提示
     * @return bool|\think\Response
     */
    protected function validateOrFail(array $data, $rules, array $messages = [])
    {
        $validate = new Validate();

        if (is_string($rules)) {
            $rules = $this->parseStringRule($rules);
        }

        foreach ($rules as $field => $rule) {
            if (is_array($rule)) {
                $validate->rule($field, implode('|', $rule));
            } else {
                $validate->rule($field, $rule);
            }
        }

        // 设置自定义消息
        if (!empty($messages)) {
            $validate->message($messages);
        }

        if (!$validate->check($data)) {
            return $this->error('参数验证失败', ['errors' => $this->formatError($validate->getError())]);
        }

        return true;
    }

    /**
     * 返回错误信息(自动替换字段名为中文)
     *
     * @param string $msg
     * @param array $extra
     * @return \think\Response
     */
    protected function error(string $msg = '操作失败', array $extra = [])
    {
        $response = ['code' => 400, 'msg' => $msg];

        if (isset($extra['errors']) && is_array($extra['errors'])) {
            $response['errors'] = $extra['errors'];
        }

        return json($response)->code(400);
    }

    /**
     * 解析字符串格式的规则为数组
     */
    private function parseStringRule(string $ruleString): array
    {
        $rules = [];
        $lines = explode(',', $ruleString);

        foreach ($lines as $line) {
            list($field, $rule) = explode(':', trim($line), 2);
            $rules[trim($field)] = explode('|', trim($rule));
        }

        return $rules;
    }

    /**
     * 格式化错误信息(将字段名替换为中文)
     */
    private function formatError(array $errors): array
    {
        $localizedErrors = [];

        foreach ($errors as $field => $error) {
            $chineseField = $this->getFieldLabel($field);
            if (is_array($error)) {
                $localizedErrors[$chineseField] = implode(', ', $error);
            } else {
                $localizedErrors[$chineseField] = $error;
            }
        }

        return $localizedErrors;
    }

    /**
     * 获取字段的中文标签
     */
    protected function getFieldLabel(string $field): string
    {
        return $this->fieldMap[$field] ?? $field;
    }

    /** 
     * 下拉菜单基本数据 1店名 2状态 3会员卡 4性别 5职业 6职务 7婚姻 8学历 9银行 10支付 11民族 12地区 13更多状态 14考勤 15企业类型 16单位 17SPH 18CYL 19ADD 20轴向 21逻辑运算
     * @param $value
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/3/23 22:18
     */
    public function BaseInfo($value){
        try {
            return Db::name('info_base')->whereIn('type', $value)->where('status', 0)->order('type')->order('sort', 'asc')->select();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /**
     * 员工基础数据查询
     * @param $value
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/3/23 22:18
     */
    public function BaseStaff($value){
        try {
            return Db::name('base_staff')->whereIn('type', $value)->whereRaw('status=0 OR status=3')->order('type')->order('sort', 'asc')->select();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /**
     * 供应商基础数据
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/3/23 22:18
     */
    public function BaseVendor(){
        try {
            return Db::name('base_vendor')->where('status', 0)->order('py', 'asc')->select();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * 查分类到下拉
     * @param $value
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/4/6 0:06
     */
    public function BaseType($value, $status){
        try {
            return Db::name('base_goods')->whereIn('type', $value)->where('status', $status)->order('type')->order('py')->select();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /**
     * 供应商分类查询
     * @param $value
     * @param $status
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/4/9 21:01
     */
    public function BaseTypeVendor($status){
        try {
            return Db::name('base_vendor')->where('status', $status)->order('py')->select();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /**
     * 获取最大值
     * @param $tablename
     * @param $type
     * @param $value
     * @param $field
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/4/6 0:06
     */
    public function BaseTypeMax($tablename, $type, $value, $field){
        try {
            return Db::name($tablename)->whereIn($type, $value)->max($field, false);
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * Goods Update
     * @param $tableName
     * @param $id
     * @param $value
     * @param $data
     * @return int|string
     * @throws \think\Exception
     * Date : 2024/4/13 20:15
     */
    public function GoodsSave($tableName, $id, $value, $data){
        $data['update_time'] = date("Y-m-d H:i:s");
        try {
            return Db::name($tableName)->where($id, $value)->update($data);
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * Goods Exp Update
     * @param $tableName
     * @param $id
     * @param $value
     * @param $data
     * @return int|string
     * @throws \think\Exception
     * Date : 2024/4/9 9:03
     */
    public function GoodsExpUpdate($tableName, $id, $value, $data){
        try {
            return Db::name($tableName)->where($id, $value)->data($data)->update();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * 查
     * @param $tableName
     * @param $key
     * @param $value
     * @return bool|\PDOStatement|string|\think\Collection
     * Date : 2024/3/16/016 2:38
     */
    public function Retrieve($tableName, $key, $value){
        try {
            return Db::name($tableName)->where($key, $value)->select();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * 改
     * @param $tableName
     * @param $id
     * @param $data
     * @return int|string
     * @throws \think\Exception
     * Date : 2024/3/16/016 2:30
     */
    public function Update($tableName, $id, $data){
        try {
            return Db::name($tableName)->where('id', $id)->data($data)->update();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * 删
     * @param $tableName
     * @param $id
     * @return int|string
     * @throws \think\Exception
     * Date : 2024/3/16/016 2:20
     */
    public function Delete($tableName, $id){
        try {
            return Db::name($tableName)->where('id', $id)->delete();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * 增 strict(false) 强制模式 避免错误
     * @param $tableName
     * @param $data
     * @return int|string
     * Date : 2024/3/16/016 1:56
     */
    public function Create($tableName, $data){
        try {
            return Db::name($tableName)->strict(false)->insert($data);
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /**
     * 统计数量
     * @param $tableName
     * @return int|string
     * Date : 2024/3/16/016 1:56
     */
    public function Count($tableName){
        try {
            return Db::name($tableName)->count();
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /** 
     * 遍历 CRUD=增删改查 $dataName, `$dataName`.
     * @param $tableName
     * @return array|mixed
     * @throws \think\db\exception\BindParamException
     * @throws \think\exception\PDOException
     * Date : 2024/3/16/016 1:52
     */
    public function throwAll($tableName){
        $str = "SELECT * FROM `$tableName`";
        return Db::query($str);
    }

    /** 
     * 删除多条数据
     * @param $tableName
     * @param $ids
     * @return string|void
     * @throws \think\Exception
     * Date : 2024/3/16/016 2:55
     */
    public function batchDelete($tableName, $ids){
        try {
            foreach($ids as $id){
                Db::name($tableName)->where('id', $id)->delete();
            }
        } catch (DbException $exception) {
            return $exception->getMessage();
        }
    }

    /******************************************************************
     *                       新增增强方法
     *             所有方法以 new 前缀命名,避免冲突
     ******************************************************************/

    /**************************
     * 新增响应方法
     **************************/

    /**
     * 成功响应(新增)
     * 
     * @param mixed $data 返回数据
     * @param string $msg 提示信息
     * @param int $code 状态码
     * @return \think\Response
     * 
     * @example
     * return $this->newSuccess($data, '操作成功');
     * return $this->newSuccess(null, '删除成功');
     */
    protected function newSuccess($data = null, string $msg = '操作成功', int $code = 1)
    {
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'time' => time(),
            'data' => $data,
        ];

        // 兼容分页数据格式
        if (isset($data['list']) && isset($data['total'])) {
            $result['count'] = $data['total'];
            $result['data'] = $data['list'];
        }

        return json($result);
    }

    /**
     * 错误响应(新增)
     * 
     * @param string $msg 错误信息
     * @param int $code 错误码
     * @param mixed $data 附加数据
     * @return \think\Response
     * 
     * @example
     * return $this->newError('参数错误');
     * return $this->newError('系统错误', 500);
     */
    protected function newError(string $msg = '操作失败', int $code = 0, $data = null)
    {
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'time' => time(),
            'data' => $data,
        ];

        return json($result);
    }

    /**
     * 分页响应(新增,兼容Layui表格)
     * 
     * @param mixed $data 数据列表
     * @param int $total 总记录数
     * @param string $msg 提示信息
     * @return \think\Response
     * 
     * @example
     * return $this->newPageResponse($list, $total);
     */
    protected function newPageResponse($data, int $total = 0, string $msg = '')
    {
        $result = [
            'code'  => 1,
            'msg'   => $msg,
            'count' => $total,
            'data'  => $data,
            'time'  => time(),
        ];

        return json($result);
    }

    /**************************
     * 新增数据库操作方法
     **************************/

    /**
     * 获取列表数据(支持分页)- 新增增强版
     * 
     * @param string $table 表名
     * @param array $where 查询条件
     * @param array $field 查询字段
     * @param string $order 排序
     * @param array $with 关联预载入
     * @param bool $paginate 是否分页
     * @return array
     * 
     * @example
     * // 不分页
     * $list = $this->newGetList('user', ['status' => 1]);
     * 
     * // 分页
     * $list = $this->newGetList('user', ['status' => 1], ['id', 'name'], 'id DESC', [], true);
     */
    protected function newGetList(string $table, array $where = [], array $field = ['*'], string $order = 'id DESC', array $with = [], bool $paginate = false): array
    {
        $query = Db::name($table)->where($where)->field($field)->order($order);

        // 关联查询
        if (!empty($with)) {
            $query->with($with);
        }

        if ($paginate) {
            $page = Request::param('page', 1);
            $limit = Request::param('limit', $this->pageSize);
            
            $result = $query->paginate([
                'list_rows' => $limit,
                'page' => $page,
            ]);
            
            return [
                'list' => $result->items(),
                'total' => $result->total(),
            ];
        } else {
            return $query->select()->toArray();
        }
    }

    /**
     * 获取单条数据 - 新增增强版
     * 
     * @param string $table 表名
     * @param array $where 查询条件
     * @param array $field 查询字段
     * @param array $with 关联预载入
     * @return array|null
     * 
     * @example
     * $user = $this->newGetOne('user', ['id' => 1]);
     */
    protected function newGetOne(string $table, array $where = [], array $field = ['*'], array $with = []): ?array
    {
        $query = Db::name($table)->where($where)->field($field);

        if (!empty($with)) {
            $query->with($with);
        }

        $result = $query->find();
        return $result ? $result->toArray() : null;
    }

    /**
     * 创建数据 - 新增增强版(自动时间戳)
     * 
     * @param string $table 表名
     * @param array $data 数据
     * @param bool $filter 是否过滤非表字段
     * @return int|string
     * 
     * @example
     * $id = $this->newCreate('user', [
     *     'name' => '张三',
     *     'email' => 'zhangsan@example.com'
     * ]);
     */
    protected function newCreate(string $table, array $data, bool $filter = true)
    {
        // 自动添加时间戳
        if (!isset($data['create_time'])) {
            $data['create_time'] = $this->newTimestamp();
        }
        if (!isset($data['update_time'])) {
            $data['update_time'] = $this->newTimestamp();
        }

        return Db::name($table)->insert($data, $filter);
    }

    /**
     * 更新数据 - 新增增强版(自动时间戳)
     * 
     * @param string $table 表名
     * @param array $where 更新条件
     * @param array $data 更新数据
     * @param bool $filter 是否过滤非表字段
     * @return int
     * 
     * @example
     * $result = $this->newUpdate('user', ['id' => 1], [
     *     'name' => '李四',
     *     'update_time' => time()
     * ]);
     */
    protected function newUpdate(string $table, array $where, array $data, bool $filter = true): int
    {
        // 自动更新更新时间
        if (!isset($data['update_time'])) {
            $data['update_time'] = $this->newTimestamp();
        }

        return Db::name($table)->where($where)->update($data, $filter);
    }

    /**
     * 删除数据(支持软删除)- 新增
     * 
     * @param string $table 表名
     * @param array $where 删除条件
     * @param bool $softDelete 是否软删除
     * @return int
     * 
     * @example
     * // 硬删除
     * $this->newDelete('user', ['id' => 1]);
     * 
     * // 软删除
     * $this->newDelete('user', ['id' => 1], true);
     */
    protected function newDelete(string $table, array $where, bool $softDelete = false): int
    {
        if ($softDelete) {
            // 软删除:更新status字段为0
            return Db::name($table)->where($where)->update([
                'status' => 0,
                'update_time' => $this->newTimestamp()
            ]);
        } else {
            // 硬删除
            return Db::name($table)->where($where)->delete();
        }
    }

    /**
     * 批量插入数据 - 新增
     * 
     * @param string $table 表名
     * @param array $data 数据数组
     * @param bool $filter 是否过滤非表字段
     * @return int
     * 
     * @example
     * $data = [
     *     ['name' => '张三', 'email' => 'zhangsan@example.com'],
     *     ['name' => '李四', 'email' => 'lisi@example.com']
     * ];
     * $this->newInsertAll('user', $data);
     */
    protected function newInsertAll(string $table, array $data, bool $filter = true): int
    {
        $time = $this->newTimestamp();
        foreach ($data as &$item) {
            if (!isset($item['create_time'])) {
                $item['create_time'] = $time;
            }
            if (!isset($item['update_time'])) {
                $item['update_time'] = $time;
            }
        }

        return Db::name($table)->insertAll($data, $filter);
    }

    /**
     * 递增字段 - 新增
     * 
     * @param string $table 表名
     * @param array $where 条件
     * @param string $field 字段名
     * @param int $step 步进值
     * @return int
     * 
     * @example
     * $this->newInc('user', ['id' => 1], 'login_count');
     */
    protected function newInc(string $table, array $where, string $field, int $step = 1): int
    {
        return Db::name($table)->where($where)->inc($field, $step)->update([
            'update_time' => $this->newTimestamp()
        ]);
    }

    /**
     * 递减字段 - 新增
     * 
     * @param string $table 表名
     * @param array $where 条件
     * @param string $field 字段名
     * @param int $step 步进值
     * @return int
     * 
     * @example
     * $this->newDec('product', ['id' => 1], 'stock');
     */
    protected function newDec(string $table, array $where, string $field, int $step = 1): int
    {
        return Db::name($table)->where($where)->dec($field, $step)->update([
            'update_time' => $this->newTimestamp()
        ]);
    }

    /**
     * 统计数量 - 新增增强版
     * 
     * @param string $table 表名
     * @param array $where 条件
     * @param string $field 字段名
     * @return int
     * 
     * @example
     * $count = $this->newCount('user', ['status' => 1]);
     */
    protected function newCount(string $table, array $where = [], string $field = '*'): int
    {
        return Db::name($table)->where($where)->count($field);
    }

    /**
     * 求和 - 新增
     * 
     * @param string $table 表名
     * @param array $where 条件
     * @param string $field 字段名
     * @return float
     * 
     * @example
     * $total = $this->newSum('order', ['status' => 1], 'amount');
     */
    protected function newSum(string $table, array $where, string $field): float
    {
        return Db::name($table)->where($where)->sum($field) ?: 0;
    }

    /**************************
     * 新增验证方法
     **************************/

    /**
     * 快速验证 - 验证字段是否为空
     * 
     * @param mixed $value 字段值
     * @param string $field 字段名
     * @return bool
     * @throws ValidateException
     * 
     * @example
     * $this->newCheckEmpty($name, '姓名');
     */
    protected function newCheckEmpty($value, string $field = ''): bool
    {
        if (empty($value) && $value !== '0' && $value !== 0) {
            throw new ValidateException($field ? $field . '不能为空' : '参数不能为空');
        }
        return true;
    }

    /**
     * 快速验证 - 验证数字范围
     * 
     * @param mixed $value 字段值
     * @param int $min 最小值
     * @param int $max 最大值
     * @param string $field 字段名
     * @return bool
     * @throws ValidateException
     * 
     * @example
     * $this->newCheckNumberRange($age, 1, 150, '年龄');
     */
    protected function newCheckNumberRange($value, int $min, int $max, string $field = ''): bool
    {
        if (!is_numeric($value) || $value < $min || $value > $max) {
            throw new ValidateException($field ? $field . '必须在' . $min . '-' . $max . '之间' : '参数范围错误');
        }
        return true;
    }

    /**
     * 快速验证 - 验证字符串长度
     * 
     * @param string $value 字段值
     * @param int $min 最小长度
     * @param int $max 最大长度
     * @param string $field 字段名
     * @return bool
     * @throws ValidateException
     * 
     * @example
     * $this->newCheckLength($name, 2, 20, '姓名');
     */
    protected function newCheckLength(string $value, int $min, int $max, string $field = ''): bool
    {
        $length = mb_strlen($value, 'utf-8');
        if ($length < $min || $length > $max) {
            throw new ValidateException($field ? $field . '长度必须在' . $min . '-' . $max . '之间' : '参数长度错误');
        }
        return true;
    }

    /**
     * 快速验证 - 验证手机号格式
     * 
     * @param string $mobile 手机号
     * @param string $field 字段名
     * @return bool
     * @throws ValidateException
     * 
     * @example
     * $this->newCheckMobile('13800138000', '手机号');
     */
    protected function newCheckMobile(string $mobile, string $field = '手机号'): bool
    {
        if (!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
            throw new ValidateException($field . '格式不正确');
        }
        return true;
    }

    /**
     * 快速验证 - 验证邮箱格式
     * 
     * @param string $email 邮箱地址
     * @param string $field 字段名
     * @return bool
     * @throws ValidateException
     * 
     * @example
     * $this->newCheckEmail('test@example.com', '邮箱');
     */
    protected function newCheckEmail(string $email, string $field = '邮箱'): bool
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new ValidateException($field . '格式不正确');
        }
        return true;
    }

    /**************************
     * 新增参数处理和安全方法
     **************************/

    /**
     * 获取请求参数(带默认值和过滤)- 新增增强版
     * 
     * @param string $key 参数名
     * @param mixed $default 默认值
     * @param string $filter 过滤方法
     * @return mixed
     * 
     * @example
     * $name = $this->newParam('name', '', 'trim');
     * $page = $this->newParam('page', 1, 'intval');
     */
    protected function newParam(string $key = '', $default = null, string $filter = '')
    {
        $value = Request::param($key, $default);
        
        if ($filter && $value !== $default) {
            if (function_exists($filter)) {
                $value = $filter($value);
            } elseif (is_callable($filter)) {
                $value = call_user_func($filter, $value);
            }
        }
        
        return $value;
    }

    /**
     * 获取所有参数(带过滤)- 新增
     * 
     * @param array $defaults 默认值数组
     * @param array $filters 过滤规则
     * @return array
     * 
     * @example
     * $data = $this->newParams([
     *     'name' => '',
     *     'age' => 0
     * ], [
     *     'name' => 'trim',
     *     'age' => 'intval'
     * ]);
     */
    protected function newParams(array $defaults = [], array $filters = []): array
    {
        $params = [];
        
        foreach ($defaults as $key => $default) {
            $filter = $filters[$key] ?? '';
            $params[$key] = $this->newParam($key, $default, $filter);
        }
        
        return $params;
    }

    /**
     * 过滤HTML标签 - 新增
     * 
     * @param string $str 要过滤的字符串
     * @param string $allowableTags 允许的标签
     * @return string
     * 
     * @example
     * $content = $this->newFilterHtml($content, '<p><br>');
     */
    protected function newFilterHtml(string $str, string $allowableTags = ''): string
    {
        return strip_tags($str, $allowableTags);
    }

    /**
     * SQL注入过滤 - 新增
     * 
     * @param string $str 要过滤的字符串
     * @return string
     * 
     * @example
     * $keyword = $this->newFilterSql($keyword);
     */
    protected function newFilterSql(string $str): string
    {
        $dangerousPatterns = [
            '/\b(union|select|insert|update|delete|drop|create|alter)\b/i',
            '/\b(and|or)\b.*\b(1=1|1=0)\b/i',
            '/\'|\"|;|\*|\#|\-\-/'
        ];
        
        return preg_replace($dangerousPatterns, '', $str);
    }

    /**************************
     * 新增工具方法
     **************************/

    /**
     * 获取当前时间戳 - 新增
     * 
     * @return string
     */
    protected function newTimestamp(): string
    {
        return date('Y-m-d H:i:s');
    }

    /**
     * 生成随机字符串 - 新增
     * 
     * @param int $length 长度
     * @param string $type 类型:number, letter, mixed
     * @return string
     * 
     * @example
     * $code = $this->newRandomString(6, 'number'); // 生成6位数字
     * $token = $this->newRandomString(32); // 生成32位混合字符串
     */
    protected function newRandomString(int $length = 6, string $type = 'mixed'): string
    {
        $number = '0123456789';
        $letter = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        
        switch ($type) {
            case 'number':
                $chars = $number;
                break;
            case 'letter':
                $chars = $letter;
                break;
            case 'mixed':
            default:
                $chars = $number . $letter;
                break;
        }
        
        $str = '';
        $max = strlen($chars) - 1;
        for ($i = 0; $i < $length; $i++) {
            $str .= $chars[mt_rand(0, $max)];
        }
        
        return $str;
    }

    /**
     * 记录操作日志 - 新增
     * 
     * @param string $action 操作描述
     * @param array $data 操作数据
     * @param string $module 模块名
     * @return bool
     * 
     * @example
     * $this->newLog('添加用户', ['name' => '张三'], 'user');
     */
    protected function newLog(string $action, array $data = [], string $module = ''): bool
    {
        $logData = [
            'module' => $module ?: Request::controller(),
            'action' => $action,
            'data' => json_encode($data, JSON_UNESCAPED_UNICODE),
            'ip' => Request::ip(),
            'user_agent' => Request::server('HTTP_USER_AGENT'),
            'create_time' => $this->newTimestamp(),
        ];
        
        // 记录到文件日志
        $logContent = sprintf(
            "[%s] %s %s %s %s\n",
            $logData['create_time'],
            $logData['module'],
            $logData['action'],
            $logData['data'],
            $logData['ip']
        );
        
        $logFile = runtime_path() . 'log/operation.log';
        file_put_contents($logFile, $logContent, FILE_APPEND | LOCK_EX);
        
        return true;
    }

    /**
     * 数组转树形结构 - 新增
     * 
     * @param array $list 数据列表
     * @param string $pk 主键字段名
     * @param string $pid 父级字段名
     * @param string $child 子级键名
     * @param int $root 根节点ID
     * @return array
     * 
     * @example
     * $tree = $this->newListToTree($list, 'id', 'pid', 'children');
     */
    protected function newListToTree(array $list, string $pk = 'id', string $pid = 'pid', string $child = 'children', int $root = 0): array
    {
        $tree = [];
        $refer = [];

        foreach ($list as $key => $data) {
            $refer[$data[$pk]] = &$list[$key];
        }

        foreach ($list as $key => $data) {
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[] = &$list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent = &$refer[$parentId];
                    $parent[$child][] = &$list[$key];
                }
            }
        }

        return $tree;
    }

    /**
     * 生成分页参数 - 新增
     * 
     * @param int $total 总记录数
     * @param int $page 当前页
     * @param int $pageSize 每页数量
     * @return array
     * 
     * @example
     * $pagination = $this->newBuildPagination(100, 1, 20);
     */
    protected function newBuildPagination(int $total, int $page = 1, int $pageSize = 20): array
    {
        $totalPage = ceil($total / $pageSize);
        
        return [
            'total' => $total,
            'page' => $page,
            'page_size' => $pageSize,
            'total_page' => $totalPage,
            'has_prev' => $page > 1,
            'has_next' => $page < $totalPage,
        ];
    }

    /**
     * 生成订单号 - 新增
     * 
     * @param string $prefix 前缀
     * @return string
     * 
     * @example
     * $orderNo = $this->newGenerateOrderNo('SO');
     */
    protected function newGenerateOrderNo(string $prefix = ''): string
    {
        return $prefix . date('YmdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
    }

    /**
     * 文件大小格式化 - 新增
     * 
     * @param int $bytes 字节数
     * @param int $decimals 小数位数
     * @return string
     * 
     * @example
     * $size = $this->newFormatBytes(1024); // 1 KB
     */
    protected function newFormatBytes(int $bytes, int $decimals = 2): string
    {
        $size = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
        $factor = floor((strlen($bytes) - 1) / 3);
        return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor];
    }

    /**
     * 检查文件扩展名是否允许 - 新增
     * 
     * @param string $filename 文件名
     * @param array $allowedExtensions 允许的扩展名
     * @return bool
     * 
     * @example
     * $allowed = $this->newCheckFileExtension('image.jpg', ['jpg', 'png', 'gif']);
     */
    protected function newCheckFileExtension(string $filename, array $allowedExtensions): bool
    {
        $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        return in_array($extension, $allowedExtensions);
    }

    /**
     * 获取客户端IP - 新增
     * 
     * @return string
     */
    protected function newGetClientIp(): string
    {
        return Request::ip();
    }

    /**
     * 获取当前URL - 新增
     * 
     * @return string
     */
    protected function newGetCurrentUrl(): string
    {
        return Request::url(true);
    }

    /**
     * 重定向(增强版)- 新增
     * 
     * @param string $url 跳转地址
     * @param array $params 参数
     * @param int $code 状态码
     * @return \think\Response
     * 
     * @example
     * return $this->newRedirect('index/index', ['id' => 1]);
     */
    protected function newRedirect(string $url, array $params = [], int $code = 302)
    {
        if (!empty($params)) {
            $url .= '?' . http_build_query($params);
        }
        return redirect($url, $code);
    }
}

完整使用示例

<?php
namespace app\controller;

use app\common\business\lib\BaseMethod;
use think\exception\ValidateException;

class Product extends BaseMethod
{
    protected $pageSize = 15;

    /**
     * 商品列表 - 混合使用新旧方法
     */
    public function index()
    {
        try {
            // 使用新增的参数获取方法
            $page = $this->newParam('page', 1, 'intval');
            $limit = $this->newParam('limit', $this->pageSize, 'intval');
            $keyword = $this->newParam('keyword', '', 'trim');
            
            // 构建查询条件
            $where = ['status' => 1];
            if ($keyword) {
                $where[] = ['name|barcode', 'like', "%{$keyword}%"];
            }
            
            // 方法1:使用原有的查询方法
            $simpleList = $this->Retrieve('product', 'status', 1);
            
            // 方法2:使用新增的分页查询方法
            $pagedResult = $this->newGetList('product', $where, ['*'], 'id DESC', [], true);
            
            // 使用新增的日志记录
            $this->newLog('查询商品列表', [
                'keyword' => $keyword,
                'page' => $page,
                'simple_count' => count($simpleList),
                'paged_count' => count($pagedResult['list'])
            ], 'product');
            
            // 使用新增的分页响应
            return $this->newPageResponse($pagedResult['list'], $pagedResult['total'], '获取成功');
            
        } catch (\Exception $e) {
            return $this->newError('获取商品列表失败:' . $e->getMessage());
        }
    }

    /**
     * 添加商品 - 展示多种验证方式
     */
    public function add()
    {
        try {
            // 使用新增的参数获取方法
            $data = $this->newParams([
                'barcode' => '',
                'name' => '',
                'price' => 0,
                'category' => '',
                'stock' => 0
            ], [
                'barcode' => 'trim',
                'name' => 'trim',
                'price' => 'floatval',
                'stock' => 'intval'
            ]);
            
            // 方法1:使用原有的验证方法
            $rules = 'barcode:required|max:50,name:required|max:100,price:required|float|gt:0,category:required|max:50,stock:number|egt:0';
            
            if (!$this->validateOrFail($data, $rules)) {
                return; // 已返回错误响应
            }
            
            // 方法2:使用新增的快速验证
            $this->newCheckEmpty($data['barcode'], '商品条码');
            $this->newCheckEmpty($data['name'], '商品名称');
            $this->newCheckNumberRange($data['price'], 0.01, 999999, '商品价格');
            $this->newCheckNumberRange($data['stock'], 0, 999999, '库存数量');
            
            // 检查条码是否重复
            $exists = $this->newGetOne('product', ['barcode' => $data['barcode']]);
            if ($exists) {
                return $this->newError('商品条码已存在');
            }
            
            // 方法1:使用原有的创建方法
            // $id = $this->Create('product', $data);
            
            // 方法2:使用新增的创建方法(自动时间戳)
            $id = $this->newCreate('product', $data);
            
            // 使用新增的日志记录
            $this->newLog('添加商品', array_merge(['id' => $id], $data), 'product');
            
            return $this->newSuccess(['id' => $id], '商品添加成功');
            
        } catch (ValidateException $e) {
            return $this->newError($e->getMessage());
        } catch (\Exception $e) {
            return $this->newError('添加商品失败:' . $e->getMessage());
        }
    }

    /**
     * 更新库存 - 展示数据库操作
     */
    public function updateStock()
    {
        try {
            $id = $this->newParam('id', 0, 'intval');
            $stock = $this->newParam('stock', 0, 'intval');
            
            $this->newCheckEmpty($id, '商品ID');
            $this->newCheckNumberRange($stock, 0, 999999, '库存数量');
            
            // 方法1:使用原有的更新方法
            // $result = $this->Update('product', $id, ['stock' => $stock]);
            
            // 方法2:使用新增的更新方法(自动时间戳)
            $result = $this->newUpdate('product', ['id' => $id], ['stock' => $stock]);
            
            // 方法3:使用新增的递减方法(适用于减少库存)
            // $result = $this->newDec('product', ['id' => $id], 'stock', 1);
            
            if ($result) {
                $this->newLog('更新库存', ['id' => $id, 'stock' => $stock], 'product');
                return $this->newSuccess(null, '库存更新成功');
            } else {
                return $this->newError('库存更新失败');
            }
            
        } catch (ValidateException $e) {
            return $this->newError($e->getMessage());
        } catch (\Exception $e) {
            return $this->newError('更新库存失败:' . $e->getMessage());
        }
    }

    /**
     * 导出商品数据 - 展示工具方法使用
     */
    public function export()
    {
        try {
            // 使用原有的查询方法
            $products = $this->throwAll('product');
            
            // 使用新增的工具方法
            $exportInfo = [
                'export_time' => $this->newTimestamp(),
                'total_count' => count($products),
                'exported_by' => 'system',
                'ip_address' => $this->newGetClientIp()
            ];
            
            // 记录日志
            $this->newLog('导出商品数据', $exportInfo, 'product');
            
            return $this->newSuccess([
                'products' => $products,
                'export_info' => $exportInfo
            ], '导出成功');
            
        } catch (\Exception $e) {
            return $this->newError('导出失败:' . $e->getMessage());
        }
    }
}

0

评论区