26、Laravel开发:搜索索引、测试与邮件通知全解析

Laravel开发:搜索索引、测试与邮件通知全解析

1. 搜索索引操作

在进行一系列操作时,若要避免触发索引响应,可以使用 withoutSyncingToSearch() 方法包裹操作。示例如下:

Review::withoutSyncingToSearch(function () {
    // 创建多个评论
    factory(Review::class, 10)->create();
});

手动触发索引有两种方式:
- 通过代码触发 :在任何Eloquent查询末尾添加 searchable() 方法,它将对查询中找到的所有记录进行索引。

Review::all()->searchable();

也可以在关系方法上运行 searchable()

$user->reviews()->searchable();

若要取消索引记录,使用 unsearchable() 方法:

Review::where('sucky', true)->unsearchable();
  • 通过命令行触发 :使用Artisan命令 php artisan scout:import App\\Review 对所有 Review 模型进行分块索引。
2. 测试相关操作
2.1 文件存储测试
  • 上传假文件 :手动创建 Symfony UploadedFile 对象用于测试。假设在 storage/tests 目录下有一个名为 for-tests.jpg 的文件。
public function test_file_should_be_stored()
{
    $path = storage_path('tests/for-tests.jpg');
    $file = new UploadedFile(
        $path, // 文件路径
        'for-tests.jpg', // 原始文件名
        'image/jpg', // MIME类型
        filesize($path), // 文件大小
        null, // 错误代码
        true // 是否处于测试模式
    );
    $this->call('post', 'upload-route', [], [], ['upload' => $file]);
    $this->assertResponseOk();
}
  • 返回假文件 :若路由期望真实文件存在,可使用Faker创建模型工厂复制图片。
$factory->define(User::class, function (Faker\Generator $faker) {
    return [
        'picture' => $faker->file(
            storage_path('tests'), // 源目录
            storage_path('app'), // 目标目录
            false // 仅返回文件名,而非完整路径
        ),
        'name' => $faker->name,
    ];
});

测试用户个人资料图片是否正确回显:

public function test_user_profile_picture_echoes_correctly()
{
    $user = factory(User::class)->create();
    $this->visit("users/{$user->id}");
    $this->see($user->picture);
}
2.2 会话测试

Laravel提供了一些方便的方法用于断言会话中是否设置了某个值:
| 方法 | 描述 | 示例 |
| ---- | ---- | ---- |
| assertSessionHas($key, $value = null) | 断言会话中某个键有值,若传入第二个参数,则断言该键的值为特定值 | $this->assertSessionHas('key', 'value'); |
| assertSessionHasAll(array $bindings) | 若传入键值对数组,断言所有键的值都匹配 | $check = ['has', 'hasWithThisValue' => 'thisValue']; $this->assertSessionHasAll($check); |
| assertSessionMissing($key) | 断言会话中某个键没有值 | $this->assertSessionMissing('key'); |
| assertSessionHasErrors($bindings = [], $format = null) | 断言会话中有错误值 | $this->post('test-route', ['failing' => 'data']); $this->assertSessionHasErrors(['name', 'email']); |
| assertHasOldInput() | 断言上一页的输入已正确闪存到会话中 | $this->post('test-route', ['failing' => 'data']); $this->assertHasOldInput(); |

2.3 缓存测试

测试使用缓存的功能很简单,直接进行操作即可:

Cache::put('key', 'value', 15);
$this->assertEquals('value', Cache::get('key'));

Laravel在测试环境中默认使用“array”缓存驱动,将缓存值存储在内存中。

2.4 cookie测试

在测试路由前设置cookie,可手动将cookie传递给 call() 方法的参数。
若要在测试期间排除cookie的加密,可让 EncryptCookies 中间件暂时为该cookie禁用自身:

use Illuminate\Cookie\Middleware\EncryptCookies;
$this->app->resolving(
    EncryptCookies::class,
    function ($object) {
        $object->disableFor('cookie-name');
    }
);

测试cookie示例:

public function test_cookie()
{
    $this->app->resolving(EncryptCookies::class, function ($object) {
        $object->disableFor('my-cookie');
    });
    $this->call('get', 'route-echoing-my-cookie-value', [], ['my-cookie' => 'baz']);
    $this->see('baz');
}

若不想禁用加密,可手动设置加密后的cookie值:

use Illuminate\Contracts\Encryption\Encrypter;
public function test_cookie()
{
    $encryptedBaz = app(Encrypter::class)->encrypt('baz');
    $this->call(
        'get',
        'route-echoing-my-cookie-value',
        [],
        ['my-cookie' => $encryptedBaz]
    );
    $this->see('baz');
}

若要测试响应中是否设置了cookie,可使用 seeCookie() seePlainCookie() 方法:

$this->visit('cookie-setting-route');
$this->seeCookie('cookie-name');
3. 邮件和通知相关操作
3.1 邮件驱动及依赖

Laravel的邮件功能基于SwiftMailer,自带Mailgun、Mandrill、Sparkpost、SES、SMTP、PHP Mail和Sendmail等驱动。使用云服务API驱动需要安装相应依赖:
- 使用云服务API驱动,需使用Composer引入Guzzle:

composer require guzzlehttp/guzzle:"~5.3|~6.0"
  • 使用SES驱动,需使用Composer引入AWS SDK:
composer require aws/aws-sdk-php:~3.0
3.2 邮件发送语法
  • “经典”邮件语法 :适用于Laravel 5.1或5.2版本。
Mail::send(
    'emails.assignment',
    ['trainer' => $trainer, 'trainee' => $trainee],
    function ($m) use ($trainer, $trainee) {
        $m->from($trainer->email, $trainer->name);
        $m->to($trainee->email, $trainee->name)->subject('A New Assignment!');
    }
);
  • “可邮寄”邮件语法 :从Laravel 5.3版本开始推荐使用。使用 make:mail Artisan命令创建可邮寄类:
php artisan make:mail Assignment

自动生成的可邮寄类示例:

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class Assignment extends Mailable
{
    use Queueable, SerializesModels;
    public function __construct()
    {
        //
    }
    public function build()
    {
        return $this->view('view.name');
    }
}

自定义可邮寄类示例:

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class Assignment extends Mailable
{
    use Queueable, SerializesModels;
    public $trainer;
    public $trainee;
    public function __construct($trainer, $trainee)
    {
        $this->trainer = $trainer;
        $this->trainee = $trainee;
    }
    public function build()
    {
        return $this->subject('New assignment from ' . $this->trainer->name)
            ->view('emails.assignment');
    }
}

发送可邮寄邮件示例:

// 简单发送
Mail::to($user)->send(new Assignment($trainer, $trainee));
// 带有抄送、密送等
Mail::to($user1)
    ->cc($user2)
    ->bcc($user3)
    ->send(new Assignment($trainer, $trainee));
// 带有集合
Mail::to('me@app.com')
    ->bcc(User::all())
    ->send(new Assignment($trainer, $trainee));
3.3 邮件模板及相关设置
  • 邮件模板 :与其他模板类似,可扩展其他模板、使用部分、解析变量等。示例模板如下:
<!-- resources/views/emails/assignment.blade.php -->
<p>Hey {{ $trainee->name }}!</p>
<p>You have received a new training assignment from <b>{{ $trainer->name }}</b>.
Check out your <a href="{{ route('training-dashboard') }}">training dashboard</a> now!</p>
  • 自定义模板变量 :在 build() 方法中使用 with() 方法明确传递给模板的变量。
public function build()
{
    return $this->subject('You have a new assignment!')
        ->view('emails.assignment')
        ->with(['assignment' => $this->event->name]);
}
  • HTML与纯文本邮件 :使用 view() 方法期望模板返回HTML,使用 text() 方法定义纯文本视图。
public function build()
{
    return $this->view('emails.reminder')
        ->text('emails.reminder_plain');
}
  • build() 方法可用的自定义方法
    | 方法 | 描述 |
    | ---- | ---- |
    | from($address, $name = null) | 设置“发件人”姓名和地址 |
    | subject($subject) | 设置邮件主题 |
    | attach($pathToFile, array $options = []) | 附加文件 |
    | attachData($data, $name, array $options = []) | 从原始字符串附加文件 |
    | priority($priority) | 设置邮件优先级,1为最高,5为最低 |
    手动修改底层Swift消息示例:
public function build()
{
    return $this->subject('Howdy!')
        ->withSwiftMessage(function ($swift) {
            $swift->setReplyTo('noreply@email.com');
        })
        ->view('emails.howdy');
}
3.4 附件和内联图像
  • 附加文件 :有两种方式附加文件。
// 使用本地文件名附加文件
public function build()
{
    return $this->subject('Your whitepaper download')
        ->attach(storage_path('pdfs/whitepaper.pdf'), [
            'mime' => 'application/pdf', // 可选
            'as' => 'whitepaper-barasa.pdf' // 可选
        ])
        ->view('emails.whitepaper');
}
// 传递原始数据附加文件
public function build()
{
    return $this->subject('Your whitepaper download')
        ->attachData(
            file_get_contents(storage_path('pdfs/whitepaper.pdf')),
            'whitepaper-barasa.pdf',
            [
                'mime' => 'application/pdf' // 可选
            ]
        )
        ->view('emails.whitepaper');
}
  • 内联图像 :在邮件中嵌入图像。
<!-- emails/image.blade.php -->
Here is an image:
<img src="{{ $message->embed(storage_path('embed.jpg')) }}">
Or, the same image embedding the data:
<img src="{{ $message->embedData(
    file_get_contents(storage_path('embed.jpg')), 'embed.jpg'
) }}">
3.5 邮件队列
  • 配置队列 :确保队列配置正确。
  • 队列发送邮件 :使用 Mail::queue() 方法将邮件对象放入队列。
Mail::queue(new Assignment($trainer, $trainee));
  • 延迟发送邮件 :使用 Mail::later() 方法添加延迟。
$when = Carbon::now()->addMinutes(30);
Mail::later($when, new Assignment($trainer, $trainee));
  • 指定队列或连接 :使用 onConnection() onQueue() 方法指定邮件添加到的队列或队列连接。
$message = (new Assignment($trainer, $trainee))
    ->onConnection('sqs')
    ->onQueue('emails');
Mail::to($user)->queue($message);
3.6 本地开发测试
  • 日志驱动 :将 MAIL_DRIVER 设置为 log ,所有尝试发送的邮件将记录到 storage/logs/laravel.log 文件中。
  • Mailtrap.io :用于在开发环境中捕获和检查邮件。注册免费账户,复制SMTP列中的用户名和密码,在 .env 文件中进行如下设置:
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username_from_mailtrap_here
MAIL_PASSWORD=your_password_from_mailtrap_here
MAIL_ENCRYPTION=null
  • 通用收件人配置 :若想在首选客户端中检查邮件,可覆盖收件人配置。

通过以上介绍,我们详细了解了Laravel中搜索索引、测试以及邮件通知的相关操作和技巧,希望能帮助开发者更好地进行项目开发和测试。

Laravel开发:搜索索引、测试与邮件通知全解析

4. 总结与对比

为了更清晰地展示上述各项操作的特点和用途,我们可以通过以下表格进行总结对比:

类别 操作 描述 示例代码
搜索索引 避免触发索引 包裹操作以避免触发索引响应 Review::withoutSyncingToSearch(function () { factory(Review::class, 10)->create(); });
搜索索引 代码触发索引 在Eloquent查询末尾添加 searchable() 方法索引记录 Review::all()->searchable();
搜索索引 命令行触发索引 使用Artisan命令对模型进行分块索引 php artisan scout:import App\\Review
搜索索引 取消索引记录 使用 unsearchable() 方法取消索引 Review::where('sucky', true)->unsearchable();
测试 - 文件存储 上传假文件 手动创建 Symfony UploadedFile 对象用于测试 见上文 test_file_should_be_stored 方法
测试 - 文件存储 返回假文件 使用Faker创建模型工厂复制图片 见上文 $factory->define(User::class) 代码块
测试 - 会话 断言会话值 多种方法用于断言会话中键值的存在情况 见上文会话测试表格
测试 - 缓存 缓存测试 直接操作缓存进行测试 Cache::put('key', 'value', 15); $this->assertEquals('value', Cache::get('key'));
测试 - cookie 设置cookie 手动传递cookie给 call() 方法参数 见上文 test_cookie 方法
测试 - cookie 排除加密 EncryptCookies 中间件为cookie禁用自身 见上文相关代码块
测试 - cookie 手动加密 手动设置加密后的cookie值 见上文相关代码块
测试 - cookie 测试响应cookie 使用 seeCookie() seePlainCookie() 方法测试 $this->visit('cookie-setting-route'); $this->seeCookie('cookie-name');
邮件 - 驱动依赖 云服务API驱动 使用Composer引入Guzzle composer require guzzlehttp/guzzle:"~5.3|~6.0"
邮件 - 驱动依赖 SES驱动 使用Composer引入AWS SDK composer require aws/aws-sdk-php:~3.0
邮件 - 发送语法 经典语法 适用于Laravel 5.1或5.2版本 见上文 Mail::send 代码块
邮件 - 发送语法 可邮寄语法 从Laravel 5.3版本开始推荐使用 见上文创建和使用可邮寄类代码块
邮件 - 模板设置 邮件模板 与其他模板类似,可扩展、解析变量等 见上文 resources/views/emails/assignment.blade.php 示例
邮件 - 模板设置 自定义变量 build() 方法中使用 with() 方法传递变量 见上文 build() 方法中使用 with() 示例
邮件 - 模板设置 HTML与纯文本 使用 view() text() 方法分别设置HTML和纯文本视图 见上文相关 build() 方法示例
邮件 - 模板设置 build() 自定义方法 多种方法用于自定义邮件消息 见上文 build() 方法可用自定义方法表格
邮件 - 附件图像 附加文件 两种方式附加文件到邮件 见上文附加文件代码块
邮件 - 附件图像 内联图像 在邮件中嵌入图像 见上文 emails/image.blade.php 示例
邮件 - 队列 队列发送 使用 Mail::queue() 方法将邮件放入队列 Mail::queue(new Assignment($trainer, $trainee));
邮件 - 队列 延迟发送 使用 Mail::later() 方法添加延迟 Mail::later(Carbon::now()->addMinutes(30), new Assignment($trainer, $trainee));
邮件 - 队列 指定队列连接 使用 onConnection() onQueue() 方法指定队列或连接 $message = (new Assignment($trainer, $trainee))->onConnection('sqs')->onQueue('emails'); Mail::to($user)->queue($message);
邮件 - 本地开发 日志驱动 设置 MAIL_DRIVER log 记录邮件到日志文件 修改 .env 文件 MAIL_DRIVER=log
邮件 - 本地开发 Mailtrap.io 用于开发环境捕获和检查邮件 修改 .env 文件相关配置
邮件 - 本地开发 通用收件人 覆盖收件人配置在首选客户端检查邮件 无具体代码,配置相关收件人信息
5. 操作流程梳理

我们可以通过以下mermaid流程图来梳理Laravel开发中邮件发送的整体操作流程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B{选择邮件发送语法}:::decision
    B -->|经典语法| C(定义视图、数据和闭包):::process
    B -->|可邮寄语法| D(使用`make:mail`命令创建可邮寄类):::process
    C --> E(调用`Mail::send()`方法发送邮件):::process
    D --> F(自定义可邮寄类的`build()`方法):::process
    F --> G(设置邮件主题、视图等):::process
    G --> H(选择是否添加附件或内联图像):::decision
    H -->|是| I(使用`attach()`或`attachData()`方法添加附件):::process
    H -->|否| J(选择是否使用队列):::decision
    I --> J
    J -->|是| K(使用`Mail::queue()`或`Mail::later()`方法放入队列):::process
    J -->|否| L(使用`Mail::send()`方法发送邮件):::process
    K --> M(指定队列或连接):::process
    M --> N(邮件发送完成):::process
    L --> N
    N --> O([结束]):::startend
6. 注意事项与最佳实践

在进行上述各项操作时,还需要注意以下几点:

6.1 搜索索引
  • 当使用 withoutSyncingToSearch() 方法包裹大量操作时,要确保后续手动触发索引,否则数据可能不会被正确索引。
  • 在手动触发索引时,对于大数据集,建议分批次进行操作,避免一次性处理过多数据导致内存溢出。
6.2 测试
  • 在进行文件存储测试时,要确保测试文件的路径和权限正确,避免因文件问题导致测试失败。
  • 会话测试中,要注意不同方法的使用场景,例如 assertSessionHasAll 方法对于数组元素的处理规则。
  • 缓存测试时,由于Laravel在测试环境默认使用“array”缓存驱动,在生产环境可能使用不同驱动,要注意缓存行为的差异。
  • cookie测试中,若使用排除加密的方法,要确保在生产环境中不会出现安全漏洞。
6.3 邮件
  • 使用云服务API驱动时,要及时更新依赖版本,确保安全性和兼容性。
  • 邮件模板中,要注意变量的传递和使用,避免出现未定义变量的错误。
  • 邮件队列配置要正确,否则可能导致邮件发送失败或延迟。
7. 常见问题及解决方案

在实际开发过程中,可能会遇到以下常见问题及对应的解决方案:

问题 可能原因 解决方案
搜索索引未触发 包裹操作时未正确使用 withoutSyncingToSearch() 方法,或未手动触发索引 检查代码中 withoutSyncingToSearch() 方法的使用,确保后续手动触发索引
文件上传测试失败 测试文件路径错误、文件权限不足或 UploadedFile 对象创建参数错误 检查测试文件路径和权限,确保 UploadedFile 对象参数正确
会话断言失败 会话中键值未正确设置或方法使用错误 检查会话中键值的设置,确认方法使用是否符合预期
缓存测试结果不一致 测试环境和生产环境缓存驱动不同 了解不同缓存驱动的特点,在测试和生产环境中保持一致或进行相应调整
cookie测试失败 未排除加密或手动加密失败 确保 EncryptCookies 中间件为cookie禁用自身,或手动加密cookie值时使用正确的加密方法
邮件发送失败 驱动配置错误、依赖未安装或队列配置错误 检查驱动配置信息,安装必要的依赖,确保队列配置正确

通过对上述Laravel开发中搜索索引、测试以及邮件通知相关内容的深入学习和实践,开发者可以更加熟练地运用这些功能,提高开发效率和项目质量。同时,在遇到问题时能够快速定位并解决,确保项目的顺利进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值