Files
tcpserver-flow/app/config/Config.php
T
2026-03-08 22:58:56 +08:00

232 lines
7.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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位机器ID00-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));
}
}