mirror of
https://devops.lemonos.cn/lawson/FendxPHP.git
synced 2026-06-15 23:12:49 +08:00
- 创建用户表(users)包含基本信息和认证字段 - 创建角色表(roles)用于权限控制 - 创建权限表(permissions)定义系统权限 - 创建用户角色关联表(user_roles)建立用户与角色关系 - 创建角色权限关联表(role_permissions)建立角色与权限关系 - 创建迁移记录表(migrations)追踪数据库变更 - 添加AdminController提供管理员面板功能 - 实现系统监控、配置管理、缓存清理等功能 - 添加AOP切面编程支持的各种通知类型 - 实现告警管理AlertManager支持多渠道告警 - 添加文档注解接口规范
253 lines
5.9 KiB
PHP
253 lines
5.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Dto;
|
|
|
|
/**
|
|
* DTO基类
|
|
* 所有数据传输对象都应该继承此类
|
|
*/
|
|
abstract class BaseDto
|
|
{
|
|
/**
|
|
* 数组转DTO
|
|
*/
|
|
public static function fromArray(array $data): static
|
|
{
|
|
$dto = new static();
|
|
|
|
foreach ($data as $key => $value) {
|
|
$method = 'set' . str_replace('_', '', ucwords($key, '_'));
|
|
|
|
if (method_exists($dto, $method)) {
|
|
$dto->$method($value);
|
|
} elseif (property_exists($dto, $key)) {
|
|
$dto->$key = $value;
|
|
}
|
|
}
|
|
|
|
return $dto;
|
|
}
|
|
|
|
/**
|
|
* DTO转数组
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
$data = [];
|
|
$reflection = new \ReflectionClass($this);
|
|
|
|
foreach ($reflection->getProperties() as $property) {
|
|
$propertyName = $property->getName();
|
|
$method = 'get' . str_replace('_', '', ucwords($propertyName, '_'));
|
|
|
|
if (method_exists($this, $method)) {
|
|
$data[$propertyName] = $this->$method();
|
|
} else {
|
|
$data[$propertyName] = $this->$propertyName ?? null;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* DTO转JSON
|
|
*/
|
|
public function toJson(): string
|
|
{
|
|
return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
|
|
}
|
|
|
|
/**
|
|
* JSON转DTO
|
|
*/
|
|
public static function fromJson(string $json): static
|
|
{
|
|
$data = json_decode($json, true);
|
|
|
|
if (!is_array($data)) {
|
|
throw new \InvalidArgumentException('Invalid JSON data');
|
|
}
|
|
|
|
return static::fromArray($data);
|
|
}
|
|
|
|
/**
|
|
* 验证DTO数据
|
|
*/
|
|
public function validate(): array
|
|
{
|
|
$errors = [];
|
|
$reflection = new \ReflectionClass($this);
|
|
|
|
foreach ($reflection->getProperties() as $property) {
|
|
$propertyName = $property->getName();
|
|
$value = $this->$propertyName ?? null;
|
|
|
|
// 检查必填字段
|
|
$attributes = $property->getAttributes('Required');
|
|
if (!empty($attributes) && ($value === null || $value === '')) {
|
|
$errors[$propertyName] = "Field {$propertyName} is required";
|
|
continue;
|
|
}
|
|
|
|
// 检查数据类型
|
|
$type = $property->getType();
|
|
if ($type && $value !== null) {
|
|
$typeName = $type->getName();
|
|
|
|
if (!$this->validateType($value, $typeName)) {
|
|
$errors[$propertyName] = "Field {$propertyName} must be of type {$typeName}";
|
|
}
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
/**
|
|
* 验证数据类型
|
|
*/
|
|
private function validateType(mixed $value, string $type): bool
|
|
{
|
|
return match ($type) {
|
|
'int', 'integer' => is_int($value),
|
|
'float', 'double' => is_float($value),
|
|
'string' => is_string($value),
|
|
'bool', 'boolean' => is_bool($value),
|
|
'array' => is_array($value),
|
|
'object' => is_object($value),
|
|
default => true,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 获取所有属性
|
|
*/
|
|
public function getProperties(): array
|
|
{
|
|
$reflection = new \ReflectionClass($this);
|
|
$properties = [];
|
|
|
|
foreach ($reflection->getProperties() as $property) {
|
|
$properties[$property->getName()] = $this->{$property->getName()} ?? null;
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* 设置属性
|
|
*/
|
|
public function setProperty(string $name, mixed $value): void
|
|
{
|
|
$method = 'set' . str_replace('_', '', ucwords($name, '_'));
|
|
|
|
if (method_exists($this, $method)) {
|
|
$this->$method($value);
|
|
} elseif (property_exists($this, $name)) {
|
|
$this->$name = $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取属性
|
|
*/
|
|
public function getProperty(string $name): mixed
|
|
{
|
|
$method = 'get' . str_replace('_', '', ucwords($name, '_'));
|
|
|
|
if (method_exists($this, $method)) {
|
|
return $this->$method();
|
|
}
|
|
|
|
return $this->$name ?? null;
|
|
}
|
|
|
|
/**
|
|
* 检查属性是否存在
|
|
*/
|
|
public function hasProperty(string $name): bool
|
|
{
|
|
return property_exists($this, $name) || method_exists($this, 'get' . str_replace('_', '', ucwords($name, '_')));
|
|
}
|
|
|
|
/**
|
|
* 克隆DTO
|
|
*/
|
|
public function clone(): static
|
|
{
|
|
return clone $this;
|
|
}
|
|
|
|
/**
|
|
* 合并另一个DTO
|
|
*/
|
|
public function merge(BaseDto $other): static
|
|
{
|
|
$newDto = $this->clone();
|
|
$otherData = $other->toArray();
|
|
|
|
foreach ($otherData as $key => $value) {
|
|
if ($value !== null) {
|
|
$newDto->setProperty($key, $value);
|
|
}
|
|
}
|
|
|
|
return $newDto;
|
|
}
|
|
|
|
/**
|
|
* 魔术方法:转换为字符串
|
|
*/
|
|
public function __toString(): string
|
|
{
|
|
return $this->toJson();
|
|
}
|
|
|
|
/**
|
|
* 魔术方法:调试输出
|
|
*/
|
|
public function __debugInfo(): array
|
|
{
|
|
return $this->toArray();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 必填字段注解
|
|
*/
|
|
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
|
class Required
|
|
{
|
|
public function __construct(public string $message = '') {}
|
|
}
|
|
|
|
/**
|
|
* 字段长度注解
|
|
*/
|
|
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
|
class Length
|
|
{
|
|
public function __construct(public int $min = 0, public int $max = 255) {}
|
|
}
|
|
|
|
/**
|
|
* 字段范围注解
|
|
*/
|
|
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
|
class Range
|
|
{
|
|
public function __construct(public mixed $min = null, public mixed $max = null) {}
|
|
}
|
|
|
|
/**
|
|
* 正则表达式注解
|
|
*/
|
|
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
|
class Pattern
|
|
{
|
|
public function __construct(public string $regex) {}
|
|
}
|