acubens
acubens

Reputation: 472

How to override Monolog core handler?

In symfony 2.5.9, I try to override SwiftMailerHandler of Monolog

class MySwiftMailerHandler extends SwiftMailerHandler
{
    public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true)
    {
         $message->setSubject('Lorem ipsum : ' . $message->getSubject()) ;
         parent::__construct($mailer, $message, $level, $bubble);
    }
}

with service

<service id="my_custom_handler" class="XXXX\Monolog\Handler\MySwiftMailerHandler">
    <tag name="monolog.handler.swift"/> <!-- which tag to use ? -->
</service>

and config

monolog:
    handlers:
        mail:
            type:         fingers_crossed
            action_level: critical
            handler:      custom #before buffered
        custom:
            type: service
            id: my_custom_handler
        #buffered:
        #    type:    buffer
        #    handler: swift
        swift:
            type:       swift_mailer
            from_email: %monolog_from_email%
            to_email:   %monolog_to_email%
            subject:    'Error'
            level:      critical

But my handler has following error : "__construct() must be an instance of Swift_Mailer, none given..."

How to create my new handler service ? Bad config monolog ? Which tag to use ? How to do ? Thanks!

Upvotes: 0

Views: 1618

Answers (2)

Davy R
Davy R

Reputation: 329

You can change the class using a compiler pass:

Symfony documentation: If you want to modify service definitions of another bundle, you can use a compiler pass to change the class of the service or to modify method calls.

// src/Kernel.php
namespace App;

// ...
+ use App\Service\YourService;
+ use Symfony\Component\DependencyInjection\ContainerBuilder;
+ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

class Kernel extends BaseKernel implements CompilerPassInterface
{
+     public function process(ContainerBuilder $container)
+     {
+         $definition = $container->findDefinition('monolog.handler.swift');
+         $definition->setClass(YourService::class);
+     }
}

Upvotes: 0

nurikabe
nurikabe

Reputation: 4010

This is tricky. All of the various handler classes are defined as parameters within monolog.xml inside of MonologBundle. (MonologExtension seems to instantiate and configure these from within a big switch statement.)

To override SwiftMailerHandler, specify the class parameter like so:

parameters: ... monolog.handler.swift_mailer.class: XXXX\Monolog\Handler\MySwiftMailerHandler

No need to muck around with services, tags, etc.

I use this approach to override SwiftMailerHandler::buildMessage() and dynamically change the subject of the email message.

Upvotes: 1

Related Questions