laravellaravel-facade

How can I override Laravel Facade methods?


I want to override the Laravels' Mail's classes facade method send (just intercept it forcing some checks and then if it passes triggering parent::send())

What is the best way to do this?


Solution

  • A Facade doesn't work like that. It's essentially kind of like a wrapper class that calls the underlying class that it represents.

    The Mail facade doesn't actually have a send method. When you do Mail::send(), under the hood, the "facade accessor" is used to reference an instance of the Illuminate\Mail\Mailer class bound in the IoC container. It's on that object the send method is called.

    The way in which you can achieve what you're after is actually a little bit trickier than it seems. What you can do is:

    That should let you hook into Laravel's Mail functionality.


    For more information, you can take a look at the following question/answer which achieves a similar thing. It extends the Mail functionality to add a new transport driver, but it takes a similar approach in that it provides its own Mailer implementation and service provider.

    Add a new transport driver to Laravel's Mailer


    app/MyMailer/Mailer.php

    <?php
    
    namespace App\MyMailer;
    
    class Mailer extends \Illuminate\Mail\Mailer
    {
        public function send($view, array $data = [], $callback = null)
        {
            // Do your checks
    
            return parent::send($view, $data, $callback);
        }
    }
    

    app/MyMailer/MailServiceProvider.php (Most of the code copied from Laravel's MailServiceProvider class)

    <?php
    
    namespace App\MyMailer;
    
    class MailServiceProvider extends \Illuminate\Mail\MailServiceProvider
    {
        public function register()
        {
            $this->registerSwiftMailer();
    
            $this->app->singleton('mailer', function ($app) {
                // This is YOUR mailer - notice there are no `use`s at the top which
                // Looks for a Mailer class in this namespace
                $mailer = new Mailer(
                    $app['view'], $app['swift.mailer'], $app['events']
                );
    
                $this->setMailerDependencies($mailer, $app);
    
    
                $from = $app['config']['mail.from'];
    
                if (is_array($from) && isset($from['address'])) {
                    $mailer->alwaysFrom($from['address'], $from['name']);
                }
    
                $to = $app['config']['mail.to'];
    
                if (is_array($to) && isset($to['address'])) {
                    $mailer->alwaysTo($to['address'], $to['name']);
                }
    
                return $mailer;
            });
        }
    }
    

    config/app.php (In the providers array)

    //...
    // Illuminate\Mail\MailServiceProvider::class,
    App\MyMailer\MailServiceProvider::class,
    //...