Logic.php 10.9 KB
<?php

namespace App\Http\Logic;

use App\Enums\Common\Code;
use App\Enums\Common\Common;
use \App\Helper\Common as CommonHelper;
use App\Exceptions\AsideGlobalException;
use App\Exceptions\BsideGlobalException;
use App\Helper\Arr;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;

/**
 * @notes: 逻辑层基类 控制器调用 统一返回 统一抛出异常
 */
class Logic
{
    protected $model;

    protected $side;

    protected $is_cache = false; //是否缓存数据

    protected $with = [];  //预加载多个关联

    /**
     * @notes: 请简要描述方法功能
     * @param array $data
     * @return array
     */
    public function success($data = [])
    {
        return $data;
    }

    /**
     * @notes: 错误抛出
     * @param string $code
     * @param string $message
     * @throws AsideGlobalException|BsideGlobalException
     */
    public function fail(string $message = "", string $code = Code::SYSTEM_ERROR)
    {
        if((request()->path()[0]) == Common::B){
            throw new BsideGlobalException($code, $message);
        }
        throw new AsideGlobalException($code, $message);
    }

    /**
     * 列表
     * @param array $map
     * @param array $sort
     * @param array $columns
     * @param int $limit
     * @return array|Model
     * @author zbj
     * @date 2023/4/13
     */
    public function getList(array $map = [], array $sort = ['sort' => 'desc'], array $columns = ['*'], int $limit = 20)
    {
        // 闭包查询条件格式化
        $query = $this->formatQuery($map);

        // 排序(支持多重排序)
        $query = $query->when($sort, function ($query, $sort) {
            foreach ($sort as $k=>$v) {
                $query->orderBy($k, $v);
            }
        });

        // 数据分页设置
        if ($limit) {
            $result = $query->with($this->with)->select($columns)->paginate($limit);
        }else{
            $result = $query->with($this->with)->select($columns)->get();
        }
        return $this->success($result ? $result->toArray() : []);
    }


    /**
     * 详情
     * @param $id
     * @return array
     * @throws AsideGlobalException|BsideGlobalException
     * @author zbj
     * @date 2023/4/13
     */
    public function getInfo($id)
    {
        $info = $this->getCacheInfo($id);
        if(!$info){
            $this->fail('数据不存在或者已经删除');
        }
        return $this->success($info->toArray());
    }

    /**
     * @param $id
     * @return mixed
     * @author zbj
     * @date 2023/4/15
     */
    public function getCacheInfo($id){
        if($this->is_cache){
            $info = Cache::get($this->getInfoCacheKey($id));
            if (!$info) {
                $info = $this->model->with($this->with)->find($id);
                if($info){
                    Cache::put($this->getInfoCacheKey($id), $info, 24 * 3600);
                }
            }
        }else{
            $info = $this->model->with($this->with)->find($id);
        }
        return $info;
    }

    /**
     * 保存
     * @param $param
     * @return array
     * @throws BsideGlobalException|AsideGlobalException
     * @author zbj
     * @date 2023/4/13
     */
    public function save($param){
        if(!empty($param['id'])){
            $this->model = $this->getCacheInfo($param['id']);
            if(!$this->model){
                $this->fail('数据不存在或者已经删除');
            }
        }else{
            Arr::forget($param, ['id']);
        }
        $columns = Schema::getColumnListing($this->model->getTable());
        foreach ($param as $name => $value){
            if(in_array($name, $columns)){
                $this->model[$name] = $value;
            }
        }
        $res = $this->model->save();
        if($res){
            //清缓存
            if($this->is_cache && !empty($param['id'])){
                $this->clearCache($param['id']);
            }
            return $this->success(['id' => $this->model->id]); //返回保存的数据id
        }else{
            $this->fail('保存失败');
        }
    }

    /**
     * 批量删除
     * @param $ids
     * @param array $map
     * @return array
     * @throws AsideGlobalException|BsideGlobalException
     * @author zbj
     * @date 2023/4/13
     */
    public function delete($ids, $map = []){
        $ids = array_filter(Arr::splitFilterToArray($ids), 'intval');
        if(!$ids){
            return $this->success();
        }

        foreach ($ids as $id){
            $model = $this->getCacheInfo($id);
            if(!$model){
                continue;
            }
            $model->delete();
            if($this->is_cache){
                $this->clearCache($id);
            }
        }

        return $this->success();
    }

    /**
     * @param $id
     * @return string
     * @author zbj
     * @date 2023/4/13
     */
    public function getInfoCacheKey($id){
        $key = $this->model->getTable() . '_info_' . $id;
        if($this->with){
            $key .= '_' . implode('_', $this->with);
        }
        return $key;
    }

    /**
     * @param $id
     * @return string
     * @author zbj
     * @date 2023/4/13
     */
    public function clearCache($id){
        Cache::forget($this->getInfoCacheKey($id));
    }

    /**
     * 设置关联查询表
     * @param $with
     * @return $this
     * @author zbj
     * @date 2023/4/26
     */
    public function setWith($with){
        $this->with = $with;
        return $this;
    }

    /**
     * 格式化查询条件
     * @param $map
     * @param $query
     * @return mixed
     * @author zbj
     * @date 2023/4/13
     */
    public function formatQuery($map, $query = '')
    {
        $model = $query ?: $this->model;
        $query = $model->where(function ($query) use ($map) {
            foreach ($map as $v) {
                if ($v instanceof \Closure) {
                    $query = $query->where($v);
                    continue;
                }
                // 判断是否是键值对类型
                if (key($v) !== 0) {
                    $key = key($v);
                    $val = $v[$key];
                    $v = [$key, is_array($val) ? 'in' : '=', $val];
                }
                switch ($v[1]) {
                    case 'like':
                        // like查询 ['name|title', 'like', '%a%']
                        if (strpos($v[0], '|') !== false) {
                            $query->where(function ($query) use ($v) {
                                $item = explode('|', $v[0]);
                                foreach ($item as $vo) {
                                    $query->orWhere($vo, $v[1], $v[2]);
                                }
                            });
                        } else {
                            $query->where($v[0], $v[1], $v[2]);
                        }
                        break;
                    case 'in':
                        // in查询 ['id', 'in', [1,2,3]]
                        if (!is_array($v[2])) {
                            $v[2] = explode(',', $v[2]);
                        }
                        $query->whereIn($v[0], $v[2]);
                        break;
                    case 'not in':
                        // not in查询 ['id', 'not in', [1,2,3]]
                        if (!is_array($v[2])) {
                            $v[2] = explode(',', $v[2]);
                        }
                        $query->whereNotIn($v[0], $v[2]);
                        break;
                    case 'between':
                        // between查询 ['created_at', 'between', ['xxx', 'xxx]]
                        if (!is_array($v[2])) {
                            $v[2] = explode(',', $v[2]);
                        }
                        $query->whereBetween($v[0], $v[2]);
                        break;
                    case 'not between':
                        // not between查询 ['created_at', 'not between', ['xxx', 'xxx]]
                        if (!is_array($v[2])) {
                            $v[2] = explode(',', $v[2]);
                        }
                        $query->whereNotBetween($v[0], $v[2]);
                        break;
                    case 'null':
                        // null查询 ['deleted_at', 'null']
                        $query->whereNull($v[0]);
                        break;
                    case "not null":
                        // not null查询 ['deleted_at', 'not null']
                        $query->whereNotNull($v[0]);
                        break;
                    case "or":
                        // or查询  [[['status'=>1],['status'=>2]], 'or'];
                        //格式:or (status=1 and status=2)
                        $where = $v[0];
                        $query->orWhere(function ($query) use ($where) {
                            // 递归解析查询条件
                            $this->formatQuery($where, $query);
                        });
                        break;
                    case 'xor':
                        // xor查询 [[['status'=>1],['status'=>2]], 'xor'];
                        // 格式:and (status=1 or status=2)
                        $where = $v[0];
                        $query->where(function ($query) use ($where) {
                            foreach ($where as $w) {
                                $query->orWhere(function ($query) use ($w) {
                                    // 递归解析查询条件
                                    $this->formatQuery([$w], $query);
                                });
                            }
                        });
                        break;
                    default:
                        // 常规查询
                        if (count($v) == 2) {
                            $query->where($v[0], '=', $v[1]);
                        } else {
                            $query->where($v[0], $v[1], $v[2]);
                        }
                        break;
                }
            }
        });
        return $query;
    }


    /**
     * @name :删除
     * @return void
     * @author :liyuhang
     * @method
     */
    public function del($map,$ids){
        $rs = $this->model->del($map);
        if($rs === false){
            $this->fail('error');
        }
        CommonHelper::del_user_cache($this->model->getTable(),$ids);
        return $this->success();
    }

    /**
     * @name :编辑
     * @return void
     * @author :liyuhang
     * @method
     */
    public function edit($map,$condition){
        $rs = $this->model->edit($map,$condition);
        if($rs === false){
            $this->fail('error');
        }
        CommonHelper::del_user_cache($this->model->getTable(),$condition['id']);
        return $this->success();
    }

    /**
     * 获取实例
     * @param mixed ...$params
     * @return static
     * @author:dc
     * @time 2023/5/11 15:23
     */
    public static function instance(...$params){
        return new static(...$params);
    }

}