如何覆盖 Laravel Facade 方法?
How can I override Laravel Facade methods?
我想覆盖 Laravels 的 Mail 的 类 外观方法发送(只是拦截它强制进行一些检查,然后如果它通过触发 parent::send())
最好的方法是什么?
Facade 不是那样工作的。它本质上有点像包装器 class,调用它所代表的底层 class。
Mail
门面实际上没有 send
方法。当您执行 Mail::send()
时,在幕后,“外观访问器”用于引用 IoC 容器中绑定的 Illuminate\Mail\Mailer
class 的实例。在那个对象上调用了 send
方法。
实现目标的方法实际上比看起来要复杂一些。您可以做的是:
- 编写您自己的
Mailer
实现,扩展 Illuminate\Mail\Mailer
,您可以在其中覆盖 send
方法,实现您的检查并调用 parent::send()
.
- 编写自己的服务提供者(扩展
Illuminate\Mail\MailServiceProvider
),特别是重新实现register
方法。它应该创建一个您自己的 Mailer
实例来代替 Laravel 自己的实例。 (您可以从 Laravel 的 register
方法中复制大部分代码)。
- 现在,在您的
config/app.php
文件中,在 providers
数组中,将 Illuminate\Mail\MailServiceProvider::class,
替换为您自己的提供商。
这应该能让您连接到 Laravel 的邮件功能。
更多信息,你可以看看下面的question/answer,它实现了类似的事情。它扩展了 Mail 功能以添加新的传输驱动程序,但它采用了类似的方法,因为它提供了自己的 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(大部分代码复制自Laravel的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(在提供者数组中)
//...
// Illuminate\Mail\MailServiceProvider::class,
App\MyMailer\MailServiceProvider::class,
//...
我想覆盖 Laravels 的 Mail 的 类 外观方法发送(只是拦截它强制进行一些检查,然后如果它通过触发 parent::send())
最好的方法是什么?
Facade 不是那样工作的。它本质上有点像包装器 class,调用它所代表的底层 class。
Mail
门面实际上没有 send
方法。当您执行 Mail::send()
时,在幕后,“外观访问器”用于引用 IoC 容器中绑定的 Illuminate\Mail\Mailer
class 的实例。在那个对象上调用了 send
方法。
实现目标的方法实际上比看起来要复杂一些。您可以做的是:
- 编写您自己的
Mailer
实现,扩展Illuminate\Mail\Mailer
,您可以在其中覆盖send
方法,实现您的检查并调用parent::send()
. - 编写自己的服务提供者(扩展
Illuminate\Mail\MailServiceProvider
),特别是重新实现register
方法。它应该创建一个您自己的Mailer
实例来代替 Laravel 自己的实例。 (您可以从 Laravel 的register
方法中复制大部分代码)。 - 现在,在您的
config/app.php
文件中,在providers
数组中,将Illuminate\Mail\MailServiceProvider::class,
替换为您自己的提供商。
这应该能让您连接到 Laravel 的邮件功能。
更多信息,你可以看看下面的question/answer,它实现了类似的事情。它扩展了 Mail 功能以添加新的传输驱动程序,但它采用了类似的方法,因为它提供了自己的 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(大部分代码复制自Laravel的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(在提供者数组中)
//...
// Illuminate\Mail\MailServiceProvider::class,
App\MyMailer\MailServiceProvider::class,
//...