Symfony 3.4/4+中如何为部分控制器修改Monolog通道
Let's break down why your Admin controllers aren't using the admin Monolog channel (even though it works for your Authenticator) and walk through how to fix it:
1. Fix Your Controller Service Configuration
Controllers in Symfony rely on specific service tags to function correctly. When you added the monolog.logger tag to your Admin controllers, you might have overwritten the default controller tag that enables argument injection.
Update your config/services.yaml to ensure your Admin controllers have both required tags:
services: # Keep your base controller configuration (if present) App\Controller\: resource: '../src/Controller' tags: ['controller.service_arguments'] # Configure Admin controllers with Monolog channel + critical controller tag App\Controller\Admin\: resource: '../src/Controller/Admin' tags: - { name: monolog.logger, channel: admin } - { name: controller.service_arguments } # Don't skip this! It enables dependency injection
2. Stop Using the AbstractController's Default Logger
Here's a common gotcha: the $logger property built into AbstractController is hardwired to the default app channel—ignoring any service tags you add. If you're using $this->logger in your Admin controllers, that's why logs still go to the app channel.
Instead, inject the logger directly into your controller (either via constructor or action argument):
namespace App\Controller\Admin; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; class DashboardController extends AbstractController { // Option 1: Constructor injection (best for repeated use) private $adminLogger; public function __construct(LoggerInterface $adminLogger) { $this->adminLogger = $adminLogger; } public function index(): Response { // This will log to the admin channel $this->adminLogger->info('Admin dashboard accessed by authenticated user'); return $this->render('admin/dashboard/index.html.twig'); } // Option 2: Action argument injection (great for one-off use) public function edit(LoggerInterface $logger): Response { $logger->debug('Starting admin resource update'); // ... rest of your logic } }
Thanks to the monolog.logger tag on your Admin controller services, Symfony automatically injects the admin channel logger whenever you type-hint LoggerInterface.
3. Verify Your Setup
To confirm everything is working as expected:
- Run
bin/console debug:container App\Controller\Admin\DashboardControllerand check theTagssection—you should seemonolog.loggerwithchannel: admin. - Run
bin/console debug:monologto confirm youradminchannel is defined and linked to a valid handler (like a stream tovar/log/admin.log). - Test your controller action, then check the
admin.logfile to see if your logs appear there.
4. Alternative: Use Attributes (Symfony 6.1+)
If you prefer a more flexible approach, you can use the #[MonologLogger] attribute to specify the channel directly on your controller or method:
namespace App\Controller\Admin; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Monolog\Attribute\MonologLogger; use Psr\Log\LoggerInterface; #[MonologLogger(channel: 'admin')] class DashboardController extends AbstractController { public function index(LoggerInterface $logger): Response { $logger->info('This log will go to the admin channel'); return $this->render('admin/dashboard/index.html.twig'); } }
This works without modifying your services.yaml tags, and lets you override the channel for individual methods if needed.
内容的提问来源于stack exchange,提问作者Alexandre Tranchant

