232 lines
7.8 KiB
PHP
232 lines
7.8 KiB
PHP
<?php
|
||
|
||
namespace app\config;
|
||
|
||
use app\config\DatabaseConfig;
|
||
use app\utils\Logger;
|
||
|
||
class Config
|
||
{
|
||
/**
|
||
* 是否使用自定义流程配置(从Config加载)
|
||
*/
|
||
public bool $flowUseCustomProcess {
|
||
get => $this->flowUseCustomProcess;
|
||
}
|
||
|
||
/**
|
||
* 自定义流程配置键名(默认使用 'standard' 注意:此次为空,并非使用自定义配置文件里面的 'standard')
|
||
*/
|
||
public string $flowProcessConfigKey {
|
||
get => $this->flowProcessConfigKey;
|
||
}
|
||
|
||
/**
|
||
* @var int 普通日志轮转时间默认 14 天
|
||
*/
|
||
public int $logRotationTimeByDay {
|
||
get => $this->logRotationTimeByDay;
|
||
}
|
||
|
||
/**
|
||
* @var int 错误日志轮转时间默认 30 天
|
||
*/
|
||
public int $errorLogRotationTimeByDay {
|
||
get => $this->errorLogRotationTimeByDay;
|
||
}
|
||
|
||
public DatabaseConfig $database {
|
||
get => $this->database;
|
||
}
|
||
|
||
public array $customProcess {
|
||
get => $this->customProcess;
|
||
}
|
||
|
||
/**
|
||
* 存储单读卡器模式
|
||
* true=单读卡器模式(一个读卡器交替入库/出库)
|
||
* false=双读卡器模式(分别使用"内镜放入"和"内镜取出"读卡器)
|
||
*/
|
||
public bool $storageSingleReader {
|
||
get => $this->storageSingleReader;
|
||
}
|
||
|
||
/**
|
||
* 机器ID,用于分布式环境,确保唯一
|
||
*/
|
||
public string $machineId {
|
||
get => $this->machineId;
|
||
}
|
||
|
||
public bool $dbDebug {
|
||
get => $this->dbDebug;
|
||
}
|
||
|
||
/**
|
||
* 方式 类:方法
|
||
* 方式 类
|
||
* 方式 :方法
|
||
* 允许使用正则 * 作为通配符
|
||
* @var array 日志过滤器
|
||
*/
|
||
public array $logFilter {
|
||
get => $this->logFilter;
|
||
}
|
||
|
||
public int $logLevel {
|
||
get => $this->logLevel;
|
||
}
|
||
|
||
/**
|
||
* 阻断模式
|
||
*/
|
||
public bool $blockMode {
|
||
get => $this->blockMode;
|
||
}
|
||
|
||
/**
|
||
* 人员刷卡记录缓存记录多久。然后是 0 表示不计算缓存时间,只要被使用了就删除
|
||
*/
|
||
public int $openCardRecordCacheTime = 0 {
|
||
get => $this->openCardRecordCacheTime;
|
||
}
|
||
|
||
/**
|
||
* 人员刷卡记录记录哪些读卡器的
|
||
* 设置为空则表示所有读卡器
|
||
*/
|
||
public array $openCardRecordReaders = [] {
|
||
get => $this->openCardRecordReaders;
|
||
}
|
||
|
||
private function __construct()
|
||
{
|
||
$this->database = new DatabaseConfig();
|
||
$this->customProcess = require __DIR__ . '/custom_process_config.php';
|
||
$this->machineId = self::getStringEnv("MACHINE_ID", "0");
|
||
if (empty($this->machineId) || $this->machineId == '0') {
|
||
$this->machineId = $this->getMachineIdByMac();
|
||
}
|
||
$this->dbDebug = self::getBoolEnv('DB_DEBUG');
|
||
$this->flowUseCustomProcess = self::getBoolEnv('FLOW_USE_CUSTOM_PROCESS', true);
|
||
$this->flowProcessConfigKey = self::getStringEnv('FLOW_PROCESS_CONFIG_KEY', '');
|
||
$this->logRotationTimeByDay = self::getIntEnv('LOG_ROTATION_TIME_BY_DAY', 14);
|
||
$this->errorLogRotationTimeByDay = self::getIntEnv('ERROR_LOG_ROTATION_TIME_BY_DAY', 30);
|
||
$this->logFilter = self::getStringArrayEnv('LOG_FILTER', []);
|
||
$this->logLevel = match (strtoupper(self::getStringEnv('LOG_LEVEL', 'DEBUG'))) {
|
||
'INFO' => \Monolog\Logger::INFO,
|
||
'WARNING' => \Monolog\Logger::WARNING,
|
||
'ERROR' => \Monolog\Logger::ERROR,
|
||
'ALERT' => \Monolog\Logger::ALERT,
|
||
'EMERGENCY' => \Monolog\Logger::EMERGENCY,
|
||
'CRITICAL' => \Monolog\Logger::CRITICAL,
|
||
'NOTICE' => \Monolog\Logger::NOTICE,
|
||
default => \Monolog\Logger::DEBUG
|
||
};
|
||
$this->blockMode = self::getBoolEnv('BLOCK_MODE', true);
|
||
$this->openCardRecordCacheTime = self::getIntEnv('OPEN_CARD_RECORD_CACHE_TIME', 60);
|
||
$this->openCardRecordReaders = self::getStringArrayEnv('OPEN_CARD_RECORD_READERS', []);
|
||
$this->storageSingleReader = self::getBoolEnv('STORAGE_SINGLE_READER', false);
|
||
}
|
||
|
||
/**
|
||
* 获取服务器MAC地址并散列成2位数字(00-99)作为机器ID
|
||
* 兼容Linux/Windows系统,失败时降级使用IP散列
|
||
*
|
||
* @return string 2位机器ID(00-99)
|
||
*/
|
||
public function getMachineIdByMac(): string
|
||
{
|
||
try {
|
||
// 步骤1:根据系统类型执行命令获取MAC地址
|
||
$mac = '';
|
||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||
// Windows系统
|
||
$output = shell_exec('ipconfig /all');
|
||
if (preg_match('/物理地址[.:\s]+([0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2})/i', $output, $matches)) {
|
||
$mac = str_replace(['-', ':'], '', strtolower($matches[1]));
|
||
}
|
||
} else {
|
||
// Linux/Mac系统
|
||
$output = shell_exec('cat /sys/class/net/*/address 2>/dev/null || ifconfig');
|
||
if (preg_match('/([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})/i', $output, $matches)) {
|
||
// 过滤虚拟网卡(docker/lo等),取第一个有效物理网卡MAC
|
||
$mac = str_replace(':', '', strtolower($matches[1]));
|
||
// 排除回环地址、docker虚拟网卡等无效MAC
|
||
$invalidPrefixes = ['00:00:00', '02:42:ac', '12:34:56'];
|
||
$isInvalid = false;
|
||
foreach ($invalidPrefixes as $prefix) {
|
||
if (str_starts_with($matches[1], $prefix)) {
|
||
$isInvalid = true;
|
||
break;
|
||
}
|
||
}
|
||
if ($isInvalid) {
|
||
$mac = '';
|
||
}
|
||
}
|
||
}
|
||
|
||
// 步骤2:若MAC获取失败,降级使用服务器IP
|
||
if (empty($mac)) {
|
||
// 获取外网/内网IP(优先内网)
|
||
$ip = $_SERVER['SERVER_ADDR'] ?? gethostbyname(gethostname());
|
||
if (empty($ip) || $ip === '127.0.0.1') {
|
||
$ip = '0.0.0.0'; // 兜底
|
||
}
|
||
$mac = $ip; // 用IP替代MAC做散列
|
||
}
|
||
|
||
$hash = md5($mac); // 生成32位哈希值
|
||
$hashInt = hexdec(substr($hash, 0, 4));
|
||
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||
$base = 62; // 62进制基数
|
||
$char1 = $chars[$hashInt % $base];
|
||
$char2 = $chars[(int)($hashInt / $base) % $base];
|
||
$machineId = $char2 . $char1;
|
||
|
||
// 步骤4:补零为2位(如5→05,99→99)
|
||
return str_pad($machineId, 2, '0', STR_PAD_LEFT);
|
||
} catch (\Exception $e) {
|
||
// 极端异常时返回默认值(建议日志记录)
|
||
Logger::error('获取机器ID失败:', ['error' => $e->getMessage()]);
|
||
return '01'; // 默认机器ID
|
||
}
|
||
}
|
||
|
||
public static function getBoolEnv($name, $default = false)
|
||
{
|
||
$value = getenv($name);
|
||
return empty($value) ? $default : filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
||
}
|
||
|
||
public static function getIntEnv($name, $default = 0)
|
||
{
|
||
$value = getenv($name);
|
||
return empty($value) ? $default : (int)$value;
|
||
}
|
||
|
||
public static function getStringEnv($name, $default = null)
|
||
{
|
||
$value = getenv($name);
|
||
return empty($value) ? $default : $value;
|
||
}
|
||
|
||
private static ?Config $instance = null;
|
||
|
||
public static function getInstance(): Config
|
||
{
|
||
if (self::$instance === null) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
private static function getStringArrayEnv(string $string, array $array): array
|
||
{
|
||
$value = getenv($string);
|
||
return empty($value) ? $array : array_map('trim', explode(';', $value));
|
||
}
|
||
|
||
} |