mirror of
https://devops.lemonos.cn/lawson/FendxPHP.git
synced 2026-06-15 23:12:49 +08:00
feat(database): 添加用户角色权限系统及相关监控功能
- 创建用户表(users)包含基本信息和认证字段 - 创建角色表(roles)用于权限控制 - 创建权限表(permissions)定义系统权限 - 创建用户角色关联表(user_roles)建立用户与角色关系 - 创建角色权限关联表(role_permissions)建立角色与权限关系 - 创建迁移记录表(migrations)追踪数据库变更 - 添加AdminController提供管理员面板功能 - 实现系统监控、配置管理、缓存清理等功能 - 添加AOP切面编程支持的各种通知类型 - 实现告警管理AlertManager支持多渠道告警 - 添加文档注解接口规范
This commit is contained in:
17
fendx-framework/fendx-cache/src/Annotation/CacheEvict.php
Normal file
17
fendx-framework/fendx-cache/src/Annotation/CacheEvict.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Fendx\Cache\Annotation;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
final class CacheEvict
|
||||
{
|
||||
public string $key;
|
||||
public bool $allEntries;
|
||||
|
||||
public function __construct(string $key = '', bool $allEntries = false)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->allEntries = $allEntries;
|
||||
}
|
||||
}
|
||||
17
fendx-framework/fendx-cache/src/Annotation/CacheUpdate.php
Normal file
17
fendx-framework/fendx-cache/src/Annotation/CacheUpdate.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Fendx\Cache\Annotation;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
final class CacheUpdate
|
||||
{
|
||||
public string $key;
|
||||
public int $ttl;
|
||||
|
||||
public function __construct(string $key = '', int $ttl = 3600)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->ttl = $ttl;
|
||||
}
|
||||
}
|
||||
19
fendx-framework/fendx-cache/src/Annotation/Cacheable.php
Normal file
19
fendx-framework/fendx-cache/src/Annotation/Cacheable.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Fendx\Cache\Annotation;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
final class Cacheable
|
||||
{
|
||||
public string $key;
|
||||
public int $ttl;
|
||||
public string $condition;
|
||||
|
||||
public function __construct(string $key = '', int $ttl = 3600, string $condition = '')
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->ttl = $ttl;
|
||||
$this->condition = $condition;
|
||||
}
|
||||
}
|
||||
231
fendx-framework/fendx-cache/src/Cache.php
Normal file
231
fendx-framework/fendx-cache/src/Cache.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Fendx\Cache;
|
||||
|
||||
use Redis;
|
||||
use RedisException;
|
||||
use Fendx\Core\Config\Config;
|
||||
use Fendx\Common\Exception\BusinessException;
|
||||
|
||||
final class Cache
|
||||
{
|
||||
private static ?Redis $redis = null;
|
||||
private static array $config = [];
|
||||
private static array $localCache = [];
|
||||
private static bool $localCacheEnabled = false;
|
||||
|
||||
public static function configure(array $config): void
|
||||
{
|
||||
self::$config = $config;
|
||||
self::$localCacheEnabled = $config['local_cache'] ?? false;
|
||||
}
|
||||
|
||||
private static function getRedis(): Redis
|
||||
{
|
||||
if (self::$redis === null) {
|
||||
self::$redis = self::createRedisConnection();
|
||||
}
|
||||
return self::$redis;
|
||||
}
|
||||
|
||||
private static function createRedisConnection(): Redis
|
||||
{
|
||||
$redis = new Redis();
|
||||
|
||||
$host = self::$config['host'] ?? '127.0.0.1';
|
||||
$port = self::$config['port'] ?? 6379;
|
||||
$password = self::$config['password'] ?? null;
|
||||
$database = self::$config['database'] ?? 0;
|
||||
$timeout = self::$config['timeout'] ?? 3.0;
|
||||
|
||||
try {
|
||||
$redis->connect($host, $port, $timeout);
|
||||
|
||||
if ($password) {
|
||||
$redis->auth($password);
|
||||
}
|
||||
|
||||
$redis->select($database);
|
||||
|
||||
return $redis;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'REDIS_CONNECT_FAILED', [
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function get(string $key, mixed $default = null): mixed
|
||||
{
|
||||
// 先检查本地缓存
|
||||
if (self::$localCacheEnabled && isset(self::$localCache[$key])) {
|
||||
$item = self::$localCache[$key];
|
||||
if ($item['expires'] > time()) {
|
||||
return $item['value'];
|
||||
}
|
||||
unset(self::$localCache[$key]);
|
||||
}
|
||||
|
||||
try {
|
||||
$value = self::getRedis()->get($key);
|
||||
|
||||
if ($value === false) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$decoded = json_decode($value, true);
|
||||
$result = is_array($decoded) ? $decoded : $value;
|
||||
|
||||
// 更新本地缓存
|
||||
if (self::$localCacheEnabled) {
|
||||
$ttl = self::getRedis()->ttl($key);
|
||||
if ($ttl > 0) {
|
||||
self::$localCache[$key] = [
|
||||
'value' => $result,
|
||||
'expires' => time() + $ttl
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_GET_FAILED', [
|
||||
'key' => $key,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function set(string $key, mixed $value, int $ttl = 3600): bool
|
||||
{
|
||||
try {
|
||||
$serialized = is_scalar($value) ? $value : json_encode($value);
|
||||
|
||||
$result = self::getRedis()->setex($key, $ttl, $serialized);
|
||||
|
||||
// 更新本地缓存
|
||||
if (self::$localCacheEnabled && $result) {
|
||||
self::$localCache[$key] = [
|
||||
'value' => $value,
|
||||
'expires' => time() + $ttl
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_SET_FAILED', [
|
||||
'key' => $key,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function delete(string $key): bool
|
||||
{
|
||||
try {
|
||||
$result = self::getRedis()->del($key);
|
||||
|
||||
// 清除本地缓存
|
||||
if (self::$localCacheEnabled) {
|
||||
unset(self::$localCache[$key]);
|
||||
}
|
||||
|
||||
return $result > 0;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_DELETE_FAILED', [
|
||||
'key' => $key,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function has(string $key): bool
|
||||
{
|
||||
try {
|
||||
return self::getRedis()->exists($key) > 0;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_HAS_FAILED', [
|
||||
'key' => $key,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function clear(): bool
|
||||
{
|
||||
try {
|
||||
$result = self::getRedis()->flushDB();
|
||||
|
||||
// 清除本地缓存
|
||||
if (self::$localCacheEnabled) {
|
||||
self::$localCache = [];
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_CLEAR_FAILED', [
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function increment(string $key, int $value = 1): int
|
||||
{
|
||||
try {
|
||||
$result = self::getRedis()->incrBy($key, $value);
|
||||
|
||||
// 清除本地缓存
|
||||
if (self::$localCacheEnabled) {
|
||||
unset(self::$localCache[$key]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_INCREMENT_FAILED', [
|
||||
'key' => $key,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function decrement(string $key, int $value = 1): int
|
||||
{
|
||||
try {
|
||||
$result = self::getRedis()->decrBy($key, $value);
|
||||
|
||||
// 清除本地缓存
|
||||
if (self::$localCacheEnabled) {
|
||||
unset(self::$localCache[$key]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (RedisException $e) {
|
||||
throw new BusinessException(500, 'CACHE_DECREMENT_FAILED', [
|
||||
'key' => $key,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function remember(string $key, callable $callback, int $ttl = 3600): mixed
|
||||
{
|
||||
$value = self::get($key);
|
||||
|
||||
if ($value === null) {
|
||||
$value = $callback();
|
||||
self::set($key, $value, $ttl);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function close(): void
|
||||
{
|
||||
if (self::$redis !== null) {
|
||||
self::$redis->close();
|
||||
self::$redis = null;
|
||||
}
|
||||
self::$localCache = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user