BaseLogic.php 9.3 KB
<?php

namespace App\Http\Logic\Bside;

use App\Enums\Common\Code;
use App\Exceptions\BsideGlobalException;
use App\Helper\Arr;
use Illuminate\Support\Facades\Cache;

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

    protected  $requestAll;

    protected $user;

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

    public function __construct()
    {
        $this->requestAll = request()->all();

        $this->user = Cache::get(request()->header('token'));
    }

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

    /**
     * @notes: 错误抛出
     * @param string $code
     * @param string $message
     * @throws BsideGlobalException
     */
    public function fail(string $message = "", string $code = Code::SYSTEM_ERROR)
    {
        throw new BsideGlobalException($code, $message);
    }


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

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

        // 数据分页设置
        if ($limit) {
            $result = $query->select($columns)->paginate($limit);
        }else{
            $result = $query->select($columns)->get();
        }

        return $this->success($result ? $result->toArray() : []);
    }


    /**
     * 详情
     * @param $id
     * @return array
     * @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->find($id);
                if($info){
                    Cache::put($this->getInfoCacheKey($id), $info);
                }
            }
        }else{
            $info = $this->model->find($id);
        }
        if($info && $info['project_id'] != $this->user['project_id']) {
            $info = null;
        }
        return $info;
    }

    /**
     * 保存
     * @param $param
     * @return array
     * @throws BsideGlobalException
     * @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('数据不存在或者已经删除');
            }
        }
        $param['project_id'] = $this->user['project_id'];
        foreach ($param as $name => $value){
            $this->model[$name] = $value;
        }

        $res = $this->model->save();

        if($res){
            //清缓存
            if($this->is_cache && !empty($param['id'])){
                Cache::forget($this->getInfoCacheKey($param['id']));
            }
            return $this->success(['id' => $this->model->id]); //返回保存的数据id
        }else{
            $this->fail('保存失败');
        }
    }

    /**
     * 批量删除
     * @param $ids
     * @return array
     * @throws BsideGlobalException
     * @author zbj
     * @date 2023/4/13
     */
    public function delete($ids){
        $ids = array_filter(Arr::splitFilterToArray($ids), 'intval');
        if(!$ids){
            $this->fail('ID不能为空');
        }
        $map[] = ['id', 'in', $ids];
        $map[] = ['project_id' => $this->user['project_id']];

        $res = $this->formatQuery($map)->delete();
        if($res){

            if($this->is_cache){
                foreach ($ids as $id){
                    Cache::forget($this->getInfoCacheKey($id));
                }
            }
            return $this->success();
        }else{
            $this->fail('删除失败');
        }
    }

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

    /**
     * 格式化查询条件
     * @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;
    }
}