【问题标题】:How can I override Laravel Facade methods?如何覆盖 Laravel Facade 方法?
【发布时间】:2016-09-22 19:24:05
【问题描述】:

我想覆盖 Laravel 的邮件类门面方法发送(只是拦截它强制进行一些检查,然后如果它通过触发 parent::send())

最好的方法是什么?

【问题讨论】:

  • 您不应该让 Mailer 执行检查,这不是它的工作,它只是发送邮件。逻辑要在外面执行,如果要发送邮件,调用send方法。
  • @tam 你在谈论可维护性和结构,我知道,最好不要将责任交给邮件程序。但问题不在于这个。

标签: laravel laravel-facade


【解决方案1】:

Facade 不能这样工作。它本质上有点像一个包装类,它调用它所代表的底层类。

Mail 外观实际上没有 send 方法。当您执行Mail::send() 时,在后台,“外观访问器”用于引用绑定在IoC 容器中的Illuminate\Mail\Mailer 类的实例。在该对象上调用了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 的邮件功能。


有关更多信息,您可以查看以下实现类似事情的问题/答案。它扩展了 Mail 功能以添加新的传输驱动程序,但它采用了类似的方法,因为它提供了自己的 Mailer 实现和服务提供者。

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(大部分代码从 Laravel 的 MailServiceProvider 类复制而来)

<?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(在 providers 数组中)

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

【讨论】:

  • 如何从回调中检索邮件?
  • 什么意思?
  • @Jonathon,我知道你很久以前就写过这个答案了。我已经使用建议的方法覆盖了 mail::send 并成功地对其进行了操作。我目前遇到的问题是我的电子邮件模板中的 $message 变量未定义(我正在使用 $message->embed 函数)。根据 laravel 文档,应该自动传递 $message 变量。我怎样才能确保继续通过而无需通过所有电子邮件模板?
猜你喜欢
  • 2021-10-11
  • 2021-11-03
  • 2017-01-17
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多