<?php/** * 案例标题:多环境配置管理 * 说明:基于.env文件管理dev/test/prod不同环境配置,运行时根据APP_ENV自动加载对应配置 * 需要安装的包: * composer require hyperf/config * composer require vlucas/phpdotenv */declare(strict_types=1);// ========== .env.dev 文件内容(放项目根目录)==========/* APP_ENV=dev APP_NAME=HyperfApp DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=hyperf_dev DB_USERNAME=root DB_PASSWORD=123456 REDIS_HOST=127.0.0.1 REDIS_PORT=6379 LOG_LEVEL=debug */// ========== .env.prod 文件内容 ==========/* APP_ENV=prod APP_NAME=HyperfApp DB_HOST=10.0.1.100 DB_PORT=3306 DB_DATABASE=hyperf_prod DB_USERNAME=hyperf_user DB_PASSWORD=StrongPassword123! REDIS_HOST=10.0.1.200 REDIS_PORT=6379 LOG_LEVEL=error */// ========== config/autoload/database.php ==========// 数据库配置文件,直接读env变量,不同环境自动切换return['default'=>['driver'=>'mysql','host'=>env('DB_HOST','127.0.0.1'),// 从环境变量读数据库地址'port'=>env('DB_PORT',3306),// 端口默认3306'database'=>env('DB_DATABASE','hyperf'),// 数据库名'username'=>env('DB_USERNAME','root'),// 用户名'password'=>env('DB_PASSWORD',''),// 密码,生产环境记得改强密码'charset'=>'utf8mb4',// 字符集,支持emoji用这个'collation'=>'utf8mb4_unicode_ci','pool'=>['min_connections'=>1,'max_connections'=>(int)env('DB_MAX_CONN',10),// 连接池大小也可以用env控制'connect_timeout'=>10.0,'wait_timeout'=>3.0,'heartbeat'=>-1,'max_idle_time'=>(float)env('DB_IDLE_TIME',60),],],];// ========== config/autoload/app.php ==========// 应用基础配置return['name'=>env('APP_NAME','HyperfSkeleton'),// 应用名称'env'=>env('APP_ENV','dev'),// 当前环境,dev/test/prod'debug'=>env('APP_DEBUG',false),// 调试模式,生产别开'timezone'=>'Asia/Shanghai',// 时区,国内项目固定上海];// ========== app/ConfigProvider.php ==========namespaceApp;classConfigProvider{publicfunction__invoke():array{return['dependencies'=>[],'commands'=>[],'listeners'=>[],];}}// ========== bin/hyperf.php 启动入口,自动加载对应env文件 ==========namespaceApp\Bootstrap;useDotenv\Dotenv;classEnvLoader{/** * 根据APP_ENV环境变量加载对应的.env文件 * 启动时先看有没有 .env.{环境名},有就加载,没有就fallback到.env */publicstaticfunctionload(string$basePath):void{$appEnv=getenv('APP_ENV')?:'dev';// 先从系统环境变量读,没有就默认dev$envFile=".env.{$appEnv}";// 拼出文件名,比如 .env.prodif(file_exists($basePath.'/'.$envFile)){// 找到了对应环境的文件,就加载它Dotenv::createImmutable($basePath,$envFile)->load();}elseif(file_exists($basePath.'/.env')){// 没有对应环境文件,fallback到默认.envDotenv::createImmutable($basePath)->load();}// 两个都没有就算了,靠系统环境变量跑}}// ========== app/Service/ConfigService.php ==========namespaceApp\Service;useHyperf\Contract\ConfigInterface;classConfigService{publicfunction__construct(privateConfigInterface$config// 注入Hyperf配置对象){}/** * 获取当前环境名,方便业务代码判断是不是生产环境 */publicfunctiongetEnv():string{return$this->config->get('app.env','dev');}/** * 判断是不是生产环境,生产环境一些敏感操作要禁掉 */publicfunctionisProduction():bool{return$this->getEnv()==='prod';}/** * 获取数据库配置,调试的时候可以打印出来看看加载的是哪个库 */publicfunctiongetDbConfig():array{return$this->config->get('database.default',[]);}}// ========== app/Controller/ConfigController.php ==========namespaceApp\Controller;useApp\Service\ConfigService;useHyperf\HttpServer\Annotation\Controller;useHyperf\HttpServer\Annotation\GetMapping;#[Controller(prefix:'/config')]classConfigController{publicfunction__construct(privateConfigService$configService){}/** * GET /config/env - 查看当前跑的是哪个环境 * 生产环境记得把这个接口干掉,别暴露配置信息 */#[GetMapping(path:'/env')]publicfunctionenv():array{// 生产环境不允许查配置,防止信息泄露if($this->configService->isProduction()){return['code'=>403,'msg'=>'生产环境禁止访问'];}return['code'=>0,'data'=>['env'=>$this->configService->getEnv(),'db_host'=>$this->configService->getDbConfig()['host']??'unknown',],];}}