Tested on Laravel 5.8
Within the source code of laravel 5.8 at this time of writing, we have this following
<?php
namespace Illuminate\Support;
// use...
abstract class Manager
{
//somewhere in the body ...
/**
* Register a custom driver creator Closure.
*
* @param string $driver
* @param \Closure $callback
* @return $this
*/
public function extend($driver, Closure $callback)
{
$this->customCreators[$driver] = $callback;
return $this;
}
// the rest of the code...
}
it means we can easily extend the driver using this manager class!
In this case I am using OutlookMailDriver, and since i am going to use the extend method from the existing manager, it expects a Closure therefore i make an invocable method that return a function.
<?php
declare(strict_types=1);
namespace App\Helpers\Drivers;
use App\Helpers\Transports\OutlookTransportManager;
use Illuminate\Mail\TransportManager;
class OutlookMailDriver
{
public function __invoke(TransportManager $manager)
{
return function ($app) {
$config = $app['config']->get('services.outlook', []);
return new OutlookTransportManager($config);
};
}
}
The signature of your invocable may differ from mine
I am going to override the registerSwiftTransport method yet calling its parent first to have it registered its expected Manager then I extend it with my custom Mail Driver.
<?php
namespace App\Providers;
use App\Helpers\Drivers\OutlookMailDriver;
use Illuminate\Mail\MailServiceProvider;
use Illuminate\Mail\TransportManager;
class CustomMailProvider extends MailServiceProvider
{
/**
* Register the Swift Transport instance.
*
* @return void
*/
protected function registerSwiftTransport()
{
parent::registerSwiftTransport();
$this->app->extend('swift.transport', function (TransportManager $transport) {
$driver = 'outlook';
$callback = new OutlookMailDriver();
$transport->extend($driver, $callback($transport));
return $transport;
});
}
}
Since Illuminate\Mail\Transport\Transport
is an abstract class therefore i need to have
send
method.
<?php
declare(strict_types=1);
namespace App\Helpers\Transports;
use Illuminate\Mail\Transport\Transport;
use Swift_Mime_SimpleMessage;
class OutlookTransportManager extends Transport
{
public function __construct($config)
{
// do your whatever you need here
}
public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
{
logger('I am using custom outlook manager');
// TODO: Implement send() method.
return 0;
}
}
comment Illuminate\Mail\MailServiceProvider::class within your config, and register your own custom provider there
return [
'providers' => [
//...
App\Providers\CustomMailProvider::class,
//Illuminate\Mail\MailServiceProvider::class, // comment this out
],
];
// somewhere in your route/web.php
Route::get('test', function () {
Mail::to('[email protected]')->send(new \App\Mail\Test());
});
How come you're extending (decorating)
TransportManager
instead of just adding a custom driver?