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:mailArtisan命令创建可邮寄类:
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开发中搜索索引、测试以及邮件通知相关内容的深入学习和实践,开发者可以更加熟练地运用这些功能,提高开发效率和项目质量。同时,在遇到问题时能够快速定位并解决,确保项目的顺利进行。
超级会员免费看
9

被折叠的 条评论
为什么被折叠?



