在基于EasySwoole框架開發項目時,合理的配置管理是項目架構中非常重要的一環。隨著項目規模的增長,配置項往往會變得越來越多,如果將所有配置都放在一個文件中,會導致配置文件臃腫、難以維護。本文將詳細介紹如何在EasySwoole中實現一個自動加載自定義配置文件夾下所有配置文件的封裝方案,使配置管理更加模塊化和規范化。
在開始自定義配置加載方案前,我們先了解一下EasySwoole的默認配置機制。
EasySwoole的默認配置文件通常位于項目根目錄下的dev.php
、produce.php
等環境相關文件中。這些文件返回一個數組,包含了框架運行所需的各種配置。
// dev.php
return [
'SERVER_NAME' => "EasySwoole",
'MN_SERVER' => [
'LISTEN_ADDRESS' => '0.0.0.0',
'PORT' => 9501,
'SERVER_TYPE' => EASYSWOOLE_WEB_SERVER,
'SOCK_TYPE' => SWOOLE_TCP,
'RUN_MODEL' => SWOOLE_PROCESS,
'SETTING' => [
'worker_num' => 8,
'reload_async' => true,
'max_wait_time' => 3
],
'TASK'=>[
'workerNum'=>4,
'maxRunningNum'=>128,
'timeout'=>15
]
],
'TEMP_DIR' => null,
'LOG_DIR' => null
];
EasySwoole在啟動時會自動加載這些配置文件,并通過Config
類實例進行管理。我們可以通過以下方式獲取配置:
$config = \EasySwoole\EasySwoole\Config::getInstance();
$serverConfig = $config->getConf('MN_SERVER');
雖然這種機制簡單直接,但在大型項目中存在以下問題:
我們的自定義配置加載方案需要實現以下目標:
我們將實現一個ConfigLoader
類,主要包含以下功能:
首先創建一個ConfigLoader
類來處理配置加載邏輯:
<?php
namespace App\Utility;
use EasySwoole\EasySwoole\Config;
class ConfigLoader
{
/**
* 加載指定目錄下的所有配置文件
* @param string $configPath 配置目錄路徑
* @param bool $mergeToGlobal 是否合并到全局配置
* @return array
*/
public static function load(string $configPath, bool $mergeToGlobal = true): array
{
if (!is_dir($configPath)) {
return [];
}
$configs = [];
$files = scandir($configPath);
foreach ($files as $file) {
if ($file === '.' || $file === '..') {
continue;
}
$filePath = $configPath . '/' . $file;
if (is_file($filePath) {
$info = pathinfo($file);
if ($info['extension'] === 'php') {
$configName = $info['filename'];
$configs[$configName] = include $filePath;
}
}
}
if ($mergeToGlobal) {
self::mergeToGlobal($configs);
}
return $configs;
}
/**
* 將配置合并到全局配置中
* @param array $configs
*/
protected static function mergeToGlobal(array $configs): void
{
$globalConfig = Config::getInstance();
foreach ($configs as $name => $config) {
$globalConfig->setConf($name, $config);
}
}
}
在EasySwooleEvent.php
的initialize
方法中調用我們的配置加載器:
use App\Utility\ConfigLoader;
public static function initialize()
{
// 其他初始化代碼...
// 加載自定義配置
$customConfigPath = EASYSWOOLE_ROOT . '/Config';
ConfigLoader::load($customConfigPath);
// 其他初始化代碼...
}
我們可以按照以下結構組織配置文件:
App/
Config/
├── database.php # 數據庫配置
├── redis.php # Redis配置
├── cache.php # 緩存配置
├── queue.php # 隊列配置
└── api.php # API相關配置
每個配置文件返回自己的配置數組:
// Config/database.php
return [
'host' => '127.0.0.1',
'port' => 3306,
'user' => 'root',
'password' => '',
'database' => 'test',
'timeout' => 5,
'charset' => 'utf8mb4',
];
現在我們可以通過統一的方式獲取配置:
// 獲取數據庫配置
$dbConfig = \EasySwoole\EasySwoole\Config::getInstance()->getConf('database');
// 獲取Redis配置
$redisConfig = \EasySwoole\EasySwoole\Config::getInstance()->getConf('redis');
在實際項目中,我們經常需要根據環境不同使用不同的配置。我們可以擴展ConfigLoader
來支持環境變量覆蓋:
public static function load(string $configPath, bool $mergeToGlobal = true): array
{
// ...之前的代碼...
foreach ($files as $file) {
// ...文件處理邏輯...
$configName = $info['filename'];
$config = include $filePath;
// 檢查是否有環境特定配置
$envConfigFile = $configPath . '/' . $configName . '_' . env('APP_ENV', 'dev') . '.php';
if (file_exists($envConfigFile)) {
$envConfig = include $envConfigFile;
$config = array_merge($config, $envConfig);
}
$configs[$configName] = $config;
}
// ...之后的代碼...
}
為了提升性能,我們可以添加配置緩存支持:
public static function load(string $configPath, bool $mergeToGlobal = true): array
{
$cacheFile = EASYSWOOLE_ROOT . '/Runtime/config_cache.php';
// 開發環境不緩存
if (env('APP_ENV', 'dev') !== 'produce' || !file_exists($cacheFile)) {
$configs = self::loadFromFiles($configPath);
// 生產環境緩存配置
if (env('APP_ENV', 'dev') === 'produce') {
file_put_contents($cacheFile, '<?php return ' . var_export($configs, true) . ';');
}
} else {
$configs = include $cacheFile;
}
if ($mergeToGlobal) {
self::mergeToGlobal($configs);
}
return $configs;
}
protected static function loadFromFiles(string $configPath): array
{
// 實現從文件加載配置的邏輯
// 同之前的load方法實現
}
對于更復雜的項目,我們可能需要支持多級配置目錄:
public static function load(string $configPath, bool $mergeToGlobal = true): array
{
$configs = [];
$dirIterator = new \RecursiveDirectoryIterator($configPath, \RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
if ($file->isFile() && $file->getExtension() === 'php') {
$relativePath = $iterator->getSubPath();
$configName = str_replace('/', '.', $relativePath . '.' . $file->getBasename('.php'));
$config = include $file->getPathname();
$configs[$configName] = $config;
}
}
if ($mergeToGlobal) {
self::mergeToGlobal($configs);
}
return $configs;
}
這樣我們可以按照目錄結構組織配置,例如:
Config/
├── db/
│ ├── master.php
│ └── slave.php
├── cache/
│ ├── redis.php
│ └── memcached.php
└── app.php
獲取配置時可以使用點語法:
$masterDbConfig = Config::getInstance()->getConf('db.master');
通過本文介紹的方法,我們實現了一個靈活、高效的EasySwoole自定義配置加載方案。該方案具有以下優點:
在實際項目中,可以根據具體需求進一步擴展此方案,例如添加配置熱更新、配置變更監聽等功能,使配置管理更加完善。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。