Symfony3日志器约定调整及向后兼容配置示例咨询
没问题,我来一步步给你拆解怎么实现这个需求,完全贴合Symfony的官方约定,还能完美保证旧代码的向后兼容~
Symfony和Monolog集成的默认约定是:每个自定义日志通道都会自动对应一个monolog.logger.{channel_name}格式的服务,不需要你手动注册这些服务,框架会帮你自动创建。
首先在Monolog的配置文件里添加你的自定义通道(比如你原来的日志器对应custom通道):
# config/packages/monolog.yaml monolog: # 这里列出你需要的自定义日志通道名称 channels: ['custom', 'payment'] handlers: # (可选)给自定义通道配置专属的日志处理器,比如输出到单独的日志文件 custom: type: stream path: '%kernel.logs_dir%/custom.log' channels: ['custom'] # 指定只处理这个通道的日志 level: debug # 日志级别 # 其他默认处理器(比如main)可以保留,不影响 main: type: stream path: '%kernel.logs_dir%/%kernel.environment%.log' level: debug channels: ['!custom', '!payment'] # 排除自定义通道的日志,避免重复记录
这段配置完成后,Symfony会自动生成monolog.logger.custom和monolog.logger.payment这两个服务,完全符合官方约定。
接下来,把你原来的旧日志器服务名称,通过DI别名映射到新的约定服务上。假设你的旧服务叫app.legacy_custom_logger,只需要在services.yaml里添加别名配置:
# config/services.yaml services: # 旧服务名称 -> 新的Symfony约定服务的别名 app.legacy_custom_logger: '@monolog.logger.custom' # 如果有多个旧日志服务,依次添加即可 app.legacy_payment_logger: '@monolog.logger.payment'
这样一来,所有原来依赖app.legacy_custom_logger的代码完全不需要修改,DI容器会自动把新的monolog.logger.custom服务注入进去,完美实现向后兼容。
不管是旧代码依赖旧服务名,还是新代码用约定的服务名,都能正常工作:
旧代码兼容示例
如果你的旧服务是通过构造函数注入的:
// src/Service/OldOrderService.php namespace App\Service; use Psr\Log\LoggerInterface; class OldOrderService { private LoggerInterface $logger; public function __construct(LoggerInterface $legacyLogger) { $this->logger = $legacyLogger; } public function processOrder() { $this->logger->info('旧服务注入的日志:订单处理完成'); } }
在services.yaml里绑定参数(如果是自动配置的话,甚至可以省略这一步,框架会自动匹配类型+参数名):
services: App\Service\OldOrderService: arguments: $legacyLogger: '@app.legacy_custom_logger'
新代码推荐写法
对于新代码,直接使用约定的服务名注入更规范:
// src/Service/NewPaymentService.php namespace App\Service; use Psr\Log\LoggerInterface; class NewPaymentService { private LoggerInterface $paymentLogger; public function __construct(LoggerInterface $paymentLogger) { $this->paymentLogger = $paymentLogger; } public function processPayment() { $this->paymentLogger->info('新约定服务注入的日志:支付成功'); } }
可以通过全局参数绑定简化配置,避免每个服务都写arguments:
services: _defaults: autowire: true autoconfigure: true bind: # 全局绑定:参数名$customLogger对应monolog.logger.custom服务 $customLogger: '@monolog.logger.custom' $paymentLogger: '@monolog.logger.payment'
这样只要构造函数里的参数名是$customLogger,框架就会自动注入对应的服务,非常方便。
可以用Symfony控制台命令检查服务别名是否正确:
php bin/console debug:container app.legacy_custom_logger
输出里会明确显示这个服务是monolog.logger.custom的别名,说明配置成功了。
内容的提问来源于stack exchange,提问作者rad11

