基类和工具类
Some checks failed
Tests / PHP 8.2 (push) Has been cancelled
Tests / PHP 8.3 (push) Has been cancelled
Tests / PHP 8.4 (push) Has been cancelled

This commit is contained in:
2025-05-04 22:42:51 +08:00
parent ba260c2bf4
commit 0bfe7786d3
6 changed files with 559 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<?php
namespace App\BaseApp;
class BaseClient
{
private static mixed $_instance;
/**
* 获取实例
* @return null|static
*/
public static function getInstance(): null|static
{
$name = get_called_class();
if (!isset(self::$_instance[$name])) {
self::$_instance[$name] = new static();
}
return self::$_instance[$name];
}
}

165
app/BaseApp/BaseController.php Executable file
View File

@@ -0,0 +1,165 @@
<?php
namespace App\BaseApp;
use App\Service\UtilsService;
use Exception;
use Illuminate\Http\JsonResponse;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class BaseController
{
protected array $insertField = [];
protected array $notRequest = [];
protected array $updateField = [];
protected $service;
public function __construct()
{
}
/**
* 获取列表
* @Method GET
* @return JsonResponse
* @throws Exception
*/
public function list(): JsonResponse
{
return jok(
$this->service->list(),
'列表获取成功'
);
}
/**
* 获取下拉列表
* @Method GET
* @return mixed
* @throws Exception
*/
public function option(): mixed
{
return jok(
$this->service->option(),
'列表获取成功'
);
}
/**
* 获取详情
*
* @Method GET
* @return JsonResponse
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
public function detail(): JsonResponse
{
$id = request()->get('id');
if (empty($id)) UtilsService::getInstance()->notFound('参数错误');
return jok(
$this->service->detail($id),
'详情获取成功'
);
}
/**
* 创建
*
* @Method POST
* @return JsonResponse
* @throws Exception
*/
public function create(): JsonResponse
{
$params = $this->checkRequiredFields(request()->post());
return jok(
$this->service->create($params),
'创建成功'
);
}
/**
* 更新
*
* @Method POST
* @return JsonResponse
* @throws Exception
*/
public function update(): JsonResponse
{
$params = $this->checkRequiredFields(request()->post(), 'update');
$id = $params['id'];
unset($params['id']);
return jok(
$this->service->update($id, $params),
'更新成功'
);
}
/**
* 删除
*
* @Method POST
* @return JsonResponse
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
public function delete(): JsonResponse
{
$id = request()->post('ids');
if (empty($id)) UtilsService::getInstance()->notFound('参数错误');
return jok(
$this->service->delete($id),
'删除成功'
);
}
/**
* 检查必填字段
*
* @Method NO
* @param array $data
* @param string $checkType
* @param bool $throw
* @return array
* @throws Exception
*/
public function checkRequiredFields(array $data = [], string $checkType = 'create', bool $throw = true): array
{
$checkFields = $checkType == 'create' ? $this->insertField : $this->updateField;
if (!empty($this->notRequest)) {
$checkFields = array_merge($this->notRequest, $checkFields);
}
$requiredFields = [];
$result = [];
foreach ($checkFields as $fieldName) {
$checkValue = $data[$fieldName] ?? '';
if (is_array($checkValue)) {
$checkValue = json_encode($checkValue);
}
if (mb_strlen(strval($checkValue)) <= 0 && !in_array($fieldName, $this->notRequest)) {
$requiredFields[] = $fieldName;
} else {
$result[$fieldName] = $checkValue;
}
}
if ($throw && $requiredFields) {
UtilsService::getInstance()->notFound('未填写的字段: ' . implode(',', $requiredFields));
}
if (!empty($requiredFields)) {
return $requiredFields;
}
return $result;
}
}

26
app/BaseApp/BaseModel.php Executable file
View File

@@ -0,0 +1,26 @@
<?php
namespace App\BaseApp;
use Illuminate\Database\Eloquent\Model;
class BaseModel extends Model
{
protected $connection = 'mysql';
public $timestamps = false;
public function getCreatedAtAttribute($value): string
{
if (empty($value)) {
return '';
}
return date('Y-m-d H:i:s', $value);
}
// 定义访问器,将 created_at 字段格式化为指定格式
public function getUpdatedAtAttribute($value): string
{
if (empty($value)) {
return '';
}
return date('Y-m-d H:i:s', $value);
}
}

70
app/BaseApp/BaseService.php Executable file
View File

@@ -0,0 +1,70 @@
<?php
namespace App\BaseApp;
use App\Models\UserModel;
use App\Service\UtilsService;
class BaseService
{
/**
* @var mixed 单例实例,确保该类只有一个全局实例
*/
private static mixed $_instance;
/**
* @var object 工具类对象,用于提供通用的功能方法
*/
protected object $utils;
/**
* @var int 用户ID默认值为0表示未登录状态
*/
protected int $userId = 0;
/**
* @var array 用户信息
*/
protected array $userInfo = [];
/**
* @var object 数据模型对象,用于数据库操作
*/
protected $model;
protected $isAuth = true;
public function __construct()
{
if ($this->isAuth) {
// 如果是home的接口可以不执行这个方法
if (!\request()->is('api/home/*')) {
$this->authUser();
}
}
$this->utils = UtilsService::getInstance();
}
/**
* 获取实例
* @return null|static
*/
public static function getInstance(): null|static
{
$name = get_called_class();
if (!isset(self::$_instance[$name])) {
self::$_instance[$name] = new static();
}
return self::$_instance[$name];
}
private function authUser()
{
$token = \request()->header('Authorization');
$token = explode(' ', $token)[1];
$userModel = UserModel::where('session_key', $token)->first();
if (!$userModel) {
jexpire('token失效');
}
$this->userId = $userModel->id;
$this->userInfo = $userModel->toArray();
}
}

55
app/Enum/ErrorEnum.php Executable file
View File

@@ -0,0 +1,55 @@
<?php
namespace App\Enum;
/**
* 状态码定义
*/
enum ErrorEnum: int
{
/**
* 成功
*/
case SUCCESS = 0;
/**
* 登录过期
*/
case NOT_AUTH = 401;
/**
* 权限不足
*/
case NOT_PERMISSION = 403;
/**
* 未找到资源的错误
*/
case NOT_FOUND = 404;
/**
* 失败状态的错误
*/
case FAIL = 500;
/**
* 验证失败的错误
*/
case NOT_VALID = 2001;
/**
* 不存在的错误
*/
case NOT_EXIST = 2002;
/**
* 不存在或已删除的错误
*/
case NOT_EXIST_OR_DELETED = 2003;
public function description(): string
{
return match ($this) {
self::SUCCESS => '请求成功',
self::FAIL => '服务器异常',
self::NOT_FOUND => '未找到资源',
self::NOT_AUTH => '未授权',
self::NOT_PERMISSION => '您没有权限',
self::NOT_VALID => '字段验证失败',
self::NOT_EXIST => '资源不存在',
self::NOT_EXIST_OR_DELETED => '资源被删除',
};
}
}

220
app/Service/UtilsService.php Executable file
View File

@@ -0,0 +1,220 @@
<?php
namespace App\Service;
use App\Enum\ErrorEnum;
use DateTime;
use Exception;
use Random\RandomException;
class UtilsService
{
private static mixed $_instance;
/**
* 获取实例
* @return null|static
*/
public static function getInstance(): null|static
{
$name = get_called_class();
if (!isset(self::$_instance[$name])) {
self::$_instance[$name] = new static();
}
return self::$_instance[$name];
}
/**
* 抛出异常
*
* @param string $msg
* @param ErrorEnum $code
* @return mixed
* @throws Exception
*/
public function errorThrow(string $msg = '请求出了问题!', ErrorEnum $code = ErrorEnum::FAIL): mixed
{
throw new Exception($msg, $code->value);
}
/**
* 抛出未找到异常 2000
*
* @param $msg
* @return mixed
* @throws Exception
*/
public function notFound($msg): mixed
{
return self::errorThrow($msg, ErrorEnum::NOT_FOUND);
}
/**
* 未授权 401
*
* @param $msg
* @return mixed
* @throws Exception
*/
public function notAuth($msg): mixed
{
exit(json_encode(['msg' => $msg, 'code' => ErrorEnum::NOT_AUTH->value]));
}
/**
* 生成密码
* @param $password
* @return string
*/
public function genPassword($password): string
{
return password_hash($password, PASSWORD_DEFAULT);
}
/**
* 密码验证
*
* @param $password
* @param $passwordAse
* @return bool
*/
public function checkPassword($password, $passwordAse): bool
{
// 盐
return password_verify($password, $passwordAse);
}
/**
* 生成OpenId
* @return string
* @throws RandomException
*/
public function genOpenId(): string
{
// 获取当前时间戳(精确到秒)
$timestamp = dechex(time());
// 生成16字节的随机数据并转换为32个十六进制字符组成的字符串
$randomString = bin2hex(random_bytes(16));
// 结合时间和随机字符串确保总长度为28个字符
return substr($timestamp . $randomString, 0, 28);
}
/**
* 递归生成树形结构
* @param $data
* @param int $pid
* @return array
*/
public function tree($data, int $pid = 0): array
{
$tree = [];
foreach ($data as $v) {
if ($v['pid'] == $pid) {
$v['children'] = $this->tree($data, $v['id']);
if (empty($v['children'])) {
unset($v['children']);
}
$tree[] = $v;
}
}
return $tree;
}
/**
* 检查手机号格式
*
* @param string $phone
* @return bool
* @throws Exception
*/
public function checkPhone(string $phone): bool
{
$phone = trim($phone);
if (preg_match('/^1[3456789]\d{9}$/', $phone)) {
return true;
} else {
self::errorThrow('手机号格式不正确');
}
}
/**
* 生成订单号
* @param int $type
* @return string
*/
public function genOrderNo(int $type = 0): string
{
$len = 9999999999;
switch ($type) {
case 0:
return 'DK'. date('Ymd') . str_pad(mt_rand(1, $len), 11, '0', STR_PAD_LEFT);
case 1:
return 'DD'. date('Ymd') . str_pad(mt_rand(1, $len), 11, '0', STR_PAD_LEFT);
default:
return '';
}
}
/**
* 是否是开发环境
* @return bool
*/
public static function isDev(): bool
{
return env('ECS') === 'localhost';
}
/**
* 根据身份证号计算年龄
* @param string $idno 身份证号15位或18位
* @return int|false 成功返回年龄失败返回false
*/
public function getAgeFromIdNo($idno = '')
{
// 校验身份证号长度
$len = strlen($idno);
if (!in_array($len, [15, 18])) {
return false;
}
// 提取出生日期部分
if ($len === 18) {
$datePart = substr($idno, 6, 8);
} else {
// 15位身份证补全年份为19XX
$datePart = '19' . substr($idno, 6, 6);
}
// 分解年月日
$year = substr($datePart, 0, 4);
$month = substr($datePart, 4, 2);
$day = substr($datePart, 6, 2);
// 校验年月日是否为数字
if (!ctype_digit($year) || !ctype_digit($month) || !ctype_digit($day)) {
return false;
}
// 尝试创建日期对象
try {
$birthDate = new DateTime("$year-$month-$day");
} catch (Exception $e) {
return false;
}
$currentDate = new DateTime();
// 检查出生日期是否在当前日期之前
if ($birthDate > $currentDate) {
return false;
}
// 计算年龄差
$ageInterval = $currentDate->diff($birthDate);
return $ageInterval->y;
}
}