编程

Laravel 动态创建 Mail、DB 和 Cache 配置

27 2024-12-25 02:01:00

通常,当处理需要配置的东西时,如数据库、缓存和邮件程序,你必须事先在各自的配置文件中定义它们。

因此,比如需要在 config/mail.php 文件中定义应用的所有邮件程序,如下所示。

return [
    'mailers' => [
        'smtp' => [
            'transport' => 'smtp',
            'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
            'port' => env('MAIL_PORT', 587),
            'encryption' => env('MAIL_ENCRYPTION', 'tls'),
            'username' => env('MAIL_USERNAME'),
            'password' => env('MAIL_PASSWORD'),
            'timeout' => null,
            'local_domain' => env('MAIL_EHLO_DOMAIN'),
        ],
        'log' => [
            'transport' => 'log',
            'channel' => env('MAIL_LOG_CHANNEL'),
        ],
    ],
];

发送邮件时,你将使用默认邮件程序或特定邮件程序。

// using the default mailer
Mail::send(new OrderShipped($order));

// specifying the mailer explicitly 
Mail::mailer('smtp')->send(new OrderShipped($order));

但是,如果你想为数据库或其他地方存储了配置的实例动态创建邮件程序呢?

这就是 Steve Bauman 贡献的新 build() 方法派上用场的地方。

  •  

Mail::build() 方法

新的 build() 方法允许你动态构建邮件程序(Mailer)。这意味着你可以动态定义邮件程序的配置,并使用它们发送邮件。

如下所示:

use Illuminate\Support\Facades\Mail;

$mailer = Mail::build([
    'transport' => 'smtp',
    'host' => '127.0.0.1',
    'port' => 587,
    'encryption' => 'tls',
    'username' => 'usr',
    'password' => 'pwd',
    'timeout' => 5,
]);

$mailer->send($mailable);

如上所述,你可以将一个配置数组传递给 build() 方法。这种配置可以来自数据库或任何你想要的地方。因此,你不需要依赖存储在 config/mail.php 中的硬编码。

邮件队列会有点小问题。就像他解释的那样,队列任务无法访问用于创建该邮件程序的配置。因此,你需要将包含 Mail::build 的作业排队,以便立即在内部发送邮件。

namespace App\Jobs;
use App\Models \Mailbox;
use Illuminate\Support\Facades \Mail;
use Illuminate\Contracts\Mail\Mailable;

class SendMailboxEmail implements ShouldQueue {
{
    public function _construct(
        public Mailbox $mailbox,
        public Mailable $email,
    ) {}

    public function handle(): void
    {
        Mail:: build([
            'transport' -> 'smtp',
            'host' = $this->mailbox->host,
            'port' => $this->mailbox->port,
            'encryption' => $this->mailbox->encryption,
            'username' => $this->mailbox->username,
            'password' = $this-›mailbox->password,
            'timeout' => 5,
        ]) ->send ($this->email);
    }
}

DB::build() 方法

类似于 Mail::build()DB::build() 方法允许动态创建应用的数据库连接。

use Illuminate\Support\Facades\DB;

$sqlite = DB::build([
    'driver' => 'sqlite',
    'database' => ':memory:',
]);

$mysql = DB::build([
    'driver' => 'mysql',
    'database' => 'forge',
    'username' => 'root',
    'password' => 'secret',
]);

下例是动态引入 SQLite 数据库的示例:

namespace App\Http\Controller;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ImportController 
{
    public function _invoke(Request $request)
    {
        $path = $request->file('database')->store();

        $sqlite = DB::build({
            'driver' => 'sqlite',
            'database' => $path,
        });

        $sqlite
            ->table('...')
            ->select([...])
            ->each(function (object $record) {
                // Perform import...
            });

        return back()->banner(
            'Successfully imported records.'
        );
    }
}

Cache::build() 方法

最后是 Cache::build() 方法,他允许你创建未在配置文件(config/cache.php)中定义的缓存库。

use Illuminate\Support\Facades\Cache;

$apc = Cache::build([
    'driver' => 'apc',
]);

$array = Cache::build([
    'driver' => 'array',
    'serialize' => false,
]);

$database = Cache::build([
    'driver' => 'database',
    'table' => 'cache',
    'connection' => null,
    'lock_connection' => null,
]);

$file = Cache::build([
    'driver' => 'file',
    'path' => storage_path('framework/cache/data'),
]);