您的当前位置:首页>全部文章>文章详情

TP6服务基类

发表于:2025-02-09 14:56:04浏览:148次TAG: #ThinkPHP #PHP

前言

在使用ThinkPHP6框架的时候,我们通过继承服务基类,可以更方便和规范编写我们的代码

示例

namespace app\services;
use app\model\User as Model;
use app\enum\User as Enum;
use app\common\basic\BaseServices;
/**
 * 授权
 * Class Auth
 * @package app\services
 */
class Auth extends BaseServices
{
    /**
     * 初始化
     */
    public function __construct()
    {
        $this->initialize(new Model(),new Enum());
    }
}

<?php
namespace app\common\basic;
use think\facade\Cache;
use think\facade\Config;
use think\exception\ValidateException;
use think\Validate;

/**
 * 基类
 * Class BaseServices
 * @package app\common\basic
 */
abstract class BaseServices
{
    // 模型
    private $model;

    // 枚举
    protected $enum;

    // 错误信息
    protected $error;

    // 不参与查询
    protected $where_except = ['time_field','date','order','pages','search_field'];

    // 不允许更新的字段
    protected $not_update_field = ['id','mer_id','create_time','update_time','delete_time'];

    // 不记录日志的表
    protected $not_log_table = ['hc_system_request','hc_system_log'];

    // 临时数据
    protected $temp;

    /**
     * 初始化
     * @param $model
     * @param $enum
     */
    protected function initialize($model,$enum)
    {
        $this->model = $model;
        $this->enum = $enum;
    }

    /**
     * 数据保存
     * @param $input
     * @param $where
     * @return bool|mixed
     */
    public function save($input,$where = [])
    {
        !$where && $where = $input['id'] ?? 0;
        $detail = $where ? $this->getOne($where) : null;
        $allowField = array_keys($this->getTableFields());
        $handle_text = '新增';
        $is_create = true;
        $action = \app\dazijie\enum\system\Log::ACTION_CREATE;
        $old = [];
        //unset($input['create_time']);
        //unset($input['update_time']);
        unset($input['delete_time']);
        if ($detail) {
            $handle_text = '修改';
            $is_false = false;
            $action = \app\dazijie\enum\system\Log::ACTION_UPDATE;
            $allowField = array_diff($allowField,$this->not_update_field);
            $old = $detail->getData();
        }
        else {
            if (empty($input['id']))
                unset($input['id']);
            $detail = $this->getModel();
        }
        if (!$detail->allowField($allowField)->save($input))
            return $this->setError("保存失败");
        $comment = $this->getTableComment();
        $this->log("{$handle_text}[ {$comment} ]",[
            'mer_id'=>$detail->mer_id?:0,
            'action'=>$action,
            'table_id'=>$detail->id,
            'old_value'=>$old,
            'new_value'=>$detail->getData()
        ]);
        $detail = $this->getOne($detail->id);
        $detail && $detail->is_create = $is_create;
        return $detail;
    }

    /**
     * 数据删除
     * @param $where
     * @param $is_true
     * @return mixed
     */
    public function delete($where,$is_true = false)
    {
        $comment = $this->getTableComment();
        $detail = $this->getOne($where);
        $mer_id = !empty($detail->mer_id) ? $detail->mer_id : 0;
        $ids = $this->getColumn($where,'id');
        if (!$ids)
            return $this->setError("删除表[ {$comment} ]记录失败,记录不存在");
        $id_str = implode(',',$ids);
        if (!$this->getModel()::destroy($ids,$is_true)) {
            return $this->setError("删除表[ {$comment} ]记录(ID集={$id_str})失败");
        }
        $this->log("删除表[ {$comment} ]记录(ID集={$id_str})成功",[
            'mer_id'=>$mer_id,
            'action'=>\app\dazijie\enum\system\Log::ACTION_DELETE,
            'table_id'=>0,
            'old_value'=>$ids,
            'new_value'=>''
        ]);
        return true;
    }

    /**
     * 增加字段值
     * @param $where
     * @param $field
     * @param int $value
     * @return mixed
     */
    public function setInc($where,$field,$value = 1)
    {
        return $this->searchBase($where)->inc($field,$value)->update();
    }
    /**
     * 减去字段值
     * @param $where
     * @param $field
     * @param int $value
     * @return mixed
     */
    public function setDec($where,$field,$value = 1)
    {
        return $this->searchBase($where)->dec($field,$value)->update();
    }
    /**
     * 求和
     * @param $where
     * @param $field
     * @return mixed
     */
    public function getSum($where,$field)
    {
        return $this->searchBase($where)->sum($field);
    }

    /**
     * 查询条数
     * @param array $where
     * @return mixed
     */
    public function getCount($where = [])
    {
        return $this->searchBase($where)->count();
    }

    /**
     * 查询重复数据
     * @param $where
     * @param $group_fields
     * @param $having_field
     * @param $having_count
     * @param array $field
     * @param array $with
     * @return mixed
     */
    public function getListSameField($where,$group_fields,$having_field,$having_count,array $field,$with = [])
    {

        $field[] = "count({$having_field}) as data_count";
        return $this->searchBase($where)
            ->fieldRaw(implode(',',$field))
            ->with($with)
            ->group($group_fields)
            ->having("data_count>{$having_count}")
            ->select();
    }

    /**
     * 分组查询
     * @param $where
     * @param $group_field
     * @param $field
     * @param $with
     * @return mixed
     */
    public function getAllByGroup($where,$group_field,$field,$with = [])
    {
        return $this->searchBase($where)
            ->with($with)
            ->field($field)
            ->group($group_field)
            ->select();
    }

    /**
     * 查询所有列表
     * @param array $where
     * @param array $with
     * @param string[] $field
     * @param array $append
     * @return mixed
     */
    public function getListAll($where = [],$with = [],$field = ['*'],$append = [])
    {
        $withCount = [];
        if (!empty($with['withCount'])) {
            $withCount = $with['withCount'];
            unset($with['withCount']);
        }
        return $this->searchBase($where)
                    ->field($field)
                    ->with($with)
                    ->withCount($withCount)
                    ->append($append)
                    ->select();
    }

    /**
     * 查询分页列表
     * @param array $where
     * @param array $with
     * @param string[] $field
     * @param array $append
     * @param array $withCount
     * @return mixed
     */
    public function getList($where = [],$with = [],$field = ['*'],$append = [])
    {
        if (!empty($where['pages']) && !empty($where['pages']['page'])  && !empty($where['pages']['limit'])) {
            $pages = [
                'page'=>$where['pages']['page'],
                'limit'=>$where['pages']['limit']
            ];
        }
        else {
            $pages = $this->getPages();
        }
        $model = $this->searchBase($where);
        $append && $model->append($append);
        $withCount = [];
        if (!empty($with['withCount'])) {
            $withCount = $with['withCount'];
            unset($with['withCount']);
        }
        return $model
            ->field($field)
            ->with($with)
            ->withCount($withCount)
            ->page($pages['page'],$pages['limit'])
            ->append($append)
            ->select();
    }

    /**
     * 获取单条数据
     * @param array $where
     * @param array $with
     * @param string[] $field
     * @param array $append
     * @return mixed
     */
    public function getOne($where = [],$with = [],$field = ['*'],$append = [])
    {
        return $this->searchBase($where)
            ->field($field)
            ->with($with)
            ->append($append)
            ->find();
    }

    /**
     * 查询列
     * @param $where
     * @param $field
     * @param string $key 作为索引
     * @return array
     */
    public function getColumn($where,$field,$key = '')
    {
        return $this->searchBase($where)->column($field,$key);
    }

    /**
     * 查询值
     * @param $where
     * @param $field
     * @return array
     */
    public function getValue($where,$field = 'id')
    {
        return $this->searchBase($where)->value($field);
    }

    /**
     * 获取最大值
     * @param $where
     * @param $field
     */
    public function getMax($where,$field)
    {
        return $this->searchBase($where)->max($field);
    }

    /**
     * 验证是否存在
     * @param $where
     * @param int $check_id
     * @return bool
     */
    public function isExist($where,$check_id = 0)
    {
        if (
            $check = $this->getOne($where)
        ) {
            if (($check_id && $check && $check->id != $check_id) || (!$check_id && $check)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取枚举
     * @return mixed
     */
    public function getEnum()
    {
        return $this->enum;
    }

    /**
     * 数据更新(DB直接更新)
     * @param $where
     * @param $data
     */
    public function update($where,$data)
    {
        return $this->searchBase($where)->update($data);
    }

    /**
     * 设置错误信息
     * @param $val
     * @return bool
     */
    public function setError($val)
    {
        $this->error = $val;
        return false;
    }

    /**
     * 获取错误信息
     * @return mixed
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * 获取分页值
     * @return array
     */
    public function getPages()
    {
        $page = request()->param('page');
        $page = $page?:1;
        $limit = request()->param('limit');
        $limit = $limit?:10;
        return compact('page','limit');
    }

    /**
     * 获取新model
     * @return mixed
     */
    public function getModel()
    {
        $class = "\\".get_class($this->model);
        return new $class;
    }

    /**
     * 事务操作
     * @param $callback
     * @param $by_bool
     * @return bool|mixed|null
     */
    public function transaction($callback,$by_bool = false)
    {
        // 回调方法返回值不为false才会提交
        if ($by_bool) {
            $model = $this->getModel();
            $model->startTrans();
            try {
                $result = null;
                if (is_callable($callback))
                    $result = call_user_func_array($callback, [$model]);
                if ($result)
                    $model->commit();
                else
                    $model->rollback();
                return $result;
            } catch (\Exception $e) {
                $model->rollback();
                // 记录日志
                $this->log($e);
                return $this->setError($e->getMessage());
            }
        }
        // 回调方法无异常才会提交
        else {
            return \think\facade\Db::transaction($callback);
        }

    }

    /**
     * 查询时间
     * @param $model
     * @param $date
     * @param string $field
     * @return mixed
     */
    private function searchTime($model,$date,$field = 'create_time')
    {
        $time = time();
        return $model
                ->when($date,function ($query) use ($date,$field,$time) {
                    switch($date){
                        case 'today':
                            $query->whereDay($field);
                            break;
                        case 'yesterday':
                            $query->whereDay($field ,'yesterday');
                            break;
                        case 'lately7':
                            $start = strtotime(date('Y-m-d', strtotime('-7 days')));
                            $query->whereBetweenTime($field, $start, $time);
                            break;
                        case 'lately30':
                            $start = strtotime(date('Y-m-d', strtotime('-30 days')));
                            $query->whereBetweenTime($field, $start, $time);
                            break;
                        case 'month':
                            $query->whereMonth($field);
                            break;
                        case 'year':
                            $query->whereYear($field);
                            break;
                        default:
                            $date = is_array($date) ? $date : explode("~",$date);
                            if (count($date) == 2) {
                                $date0 = trim($date[0]);
                                $date1 = trim($date[1]);
                                if (in_array($date0,['<','<=','>','>='])) {
                                    $end = is_numeric($date1) ? $date1 : strtotime($date1. " 23:59:59");
                                    $query->whereTime($field,$date0,$end);
                                }
                                else if ($date0 == 'day') {
                                    $query->whereDay($field,$date1);
                                }
                                else if ($date0 == 'week') {
                                    $query->whereWeek($field,$date1);
                                }
                                else if ($date0 == 'month') {
                                    $query->whereMonth($field,$date1);
                                }
                                else {
                                    $date0_c = count(explode("-",$date0));
                                    $date1_c = count(explode("-",$date1));
                                    if ($date0_c == 1) {
                                        $date0 = $date0.'-01-01';
                                    }
                                    else if ($date0_c == 2) {
                                        $date0 = $date0.'-01';
                                    }
                                    if ($date1_c == 1) {
                                        $date1 = $date1.'-01-01';
                                    }
                                    else if ($date1_c == 2) {
                                        $date1 = date("Y-m-t", strtotime($date1.'-01'));
                                    }
                                    $start = is_numeric($date0) ? $date0 : strtotime($date0. " 00:00:00");
                                    $end = is_numeric($date1) ? $date1 : strtotime($date1. " 23:59:59");
                                    $query->whereBetweenTime($field, $start, $end);
                                }
                            }
                            break;
                    }
                });
    }

    /**
     * 查询条件初始化处理
     * @param $where
     * @return array|mixed
     */
    protected function handleWhere($where)
    {
        $where = array_merge([
            'id'=>NULL,
            'mer_id'=>NULL,
            'search_field'=>NULL,
            'search_word'=>NULL,
            'time_field'=>'create_time',
            'date'=>NULL,
            'order'=>[
                'create_time'=>'desc',
                'id'=>'desc',
            ]
        ],$this->getTableFields(),$where);
        $except = ['time_field','date','order','pages','search_field'];
        foreach ($where as $field=>$item) {
            if (!in_array($field,$except)) {
                if (is_array($item)) {
                    $fh = $item[0];
                    $value = $item[1];
                }
                else {
                    if ($field == 'search_word') {
                        $fh = 'LIKE';
                    }
                    else {
                        $fh = '=';
                    }
                    $value = $item;
                }
                $where[$field] = [$fh,$value];
            }
        }
        return $where;
    }
    /**
     * 基础查询
     * 若是需要 find in set 查询,则以数组方式传入
     * @param $where
     * @return mixed
     */
    public function searchBase($where)
    {
        $where = is_array($where) ? $where : ['id'=>$where];
        $table_fields = $this->getTableFields();
        $where = $this->handleWhere($where);
        $model = $this->getModel();
        // 常规查询
        foreach ($where as $field=>$item) {
            if (!in_array($field,$this->where_except)) {
                $is_search = 1;
                // 有些字段是如: nickname|username 这种,要验证数据库是否存在该字段,不存在则不执行查询
                $field_arr = explode('|',$field);
                foreach ($field_arr as $field_item) {
                    // 不能用isset,当值为null时候,isset也是返回false
                    array_key_exists($field_item,$table_fields)===FALSE && $is_search = 0;
                }
                if ($is_search) {
                    $model = $model->when($item[1]!==NULL,function ($que) use ($item,$field){
                        $que->where($field,$item[0],$item[1]);
                    });
                }
            }
        }
        // 日期
        !empty($where['date']) && $model = $this->searchTime($model,$where['date'],!empty($where['time_field']) ? $where['time_field'] : 'create_time');
        // 模糊查询
        $model = $model
            ->when($where['search_word'][1]!==NULL && $where['search_field']!==NULL,function ($que) use ($where) {
                $que->where($where['search_field'],$where['search_word'][0], '%' . $where['search_word'][1] . '%');
            });
        // 排序
        $model = $model
            ->order($where['order']);
        return $model;
    }

    /**
     * 操作日志
     * @param $content
     * @param array $ext
     * @return bool
     */
    public function log($content,$ext = [])
    {
        // TODO
    }

    /**
     * 验证数据
     * @access protected
     * @param  array        $data     数据
     * @param  string|array $validate 验证器名或者验证规则数组
     * @param  array        $message  提示信息
     * @param  bool         $batch    是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                list($validate, $scene) = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : app()->parseClass('validate', $validate);
            $v     = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }
        $v->message($message);
        // 是否批量验证
        if ($batch) {
            $v->batch(true);
        }
        return $v->failException(true)->check($data);
    }

    /**
     * 设置临时数据
     * @param $value
     * @param $type
     * @return true
     */
    public function setTempData($value,$type = 'reset')
    {
        if ($type == 'push') {
            if (!$this->temp)
                $this->temp = [];
            array_push($this->temp,$value);
        }
        else
            $this->temp = $value;
        return true;
    }

    /**
     * 获取临时数据
     * @return mixed
     */
    public function getTempData()
    {
        return $this->temp;
    }

    /**
     * 清除临时数据
     * @return true
     */
    public function clearTempData()
    {
        $this->temp = [];
        return true;
    }
    /**
     * 获取表注释
     * @param string $table
     * @return mixed
     */
    protected function getTableComment($table = '')
    {
        !$table && $table = $this->getModel()->getTable();
        $cache_key = 'table_comment_'.$table;
        $data = \think\facade\Cache::get($cache_key);
        if (env('site.dev') || !$data) {
            $database = \think\facade\Db::query("SELECT DATABASE()")[0]['DATABASE()'];
            $info = \think\facade\Db::query("SELECT TABLE_NAME,TABLE_COMMENT FROM information_schema.`TABLES` WHERE TABLE_NAME = '{$table}' AND TABLE_SCHEMA = '{$database}'");
            $data = $info[0]['TABLE_COMMENT'];
        }
        return $data;
    }

    /**
     * 获取表字段
     * @param string $table
     * @return array|mixed
     */
    protected function getTableFields($table = '')
    {
        !$table && $table = $this->getModel()->getTable();
        $cache_key = 'table_fields_'.$table;
        $data = \think\facade\Cache::get($cache_key);
        if (env('site.dev') || !$data) {
            $res = \think\facade\Db::query("show full columns from {$table}");
            $data = [];
            foreach ($res as $item) {
                $data[$item['Field']] = NULL;
            }
            \think\facade\Cache::set($cache_key,$data,3600);
        }
        return $data;
    }

    /**
     * 获取用户当前终端
     * @return string
     */
    public function getTerminal()
    {
        if ($this->isApi()) {
            $terminal = \app\dazijie\enum\Cache::TERMINAL_API;
        }
        else if ($this->isRoutine()) {
            $terminal = \app\dazijie\enum\Cache::TERMINAL_ROUTINE;
        }
        else if ($this->isApp()) {
            $terminal = \app\dazijie\enum\Cache::TERMINAL_APP;
        }
        else if ($this->isMobile()) {
            $terminal = \app\dazijie\enum\Cache::TERMINAL_MOBILE;
        }
        else {
            $terminal = \app\dazijie\enum\Cache::TERMINAL_PC;
        }
        return $terminal;
    }
    /**
     * 是否是API端
     * @return bool
     */
    public function isApi()
    {
        $terminal = \request()->header('Terminal');
        return $terminal == "api";
    }

    /**
     * 是否是手机端
     * @return bool
     */
    public function isMobile()
    {
        return \request()->isMobile();
    }

    /**
     * 是否是微信端
     * @return bool
     */
    public function isWechat()
    {
        return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
    }

    /**
     * 是否是小程序端
     * @return bool
     */
    public function isRoutine()
    {
        $terminal = \request()->header('Terminal');
        return $terminal == "routine";
    }

    /**
     * 是否是app端
     * @return bool
     */
    public function isApp()
    {
        $terminal = \request()->header('Terminal');
        return $terminal == "app";
    }

    /**
     * 是否是pc端
     * @return bool
     */
    public function isPc()
    {
        return $this->isMobile() === false;
    }
}