Laravel 开发实用技巧:输出处理、测试与常用工具
在 Laravel 开发中,我们常常会遇到各种需求,比如处理命令输出、进行任务调度、测试代码以及使用各种实用的辅助函数和集合操作。下面将详细介绍这些方面的内容和使用方法。
命令输出处理
在 Laravel 中,对于命令的输出处理有多种方式。
-
追加输出到文件
:如果想将命令的输出追加到文件中,可以使用
appendOutputTo()
方法。示例如下:
$schedule->command('do:thing')->daily()->appendOutputTo($filePath);
-
将输出通过邮件发送
:若要将输出通过邮件发送给指定收件人,需要先将输出写入文件,再使用
emailOutputTo()方法。示例如下:
$schedule->command('do:thing')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('me@myapp.com');
需要注意的是,要确保 Laravel 的基本邮件配置正确。而且,
sendOutputTo()
、
appendOutputTo()
和
emailOutputTo()
方法仅适用于命令调度任务,不能用于闭包调度事件。
-
使用 HTTP “ping” 进行监控
:为了确保任务正确运行,可以使用一些服务进行监控,如 Laravel Envoyer 和 Dead Man’s Snitch。这些服务期望接收 HTTP “ping”,Laravel 提供了
pingBefore()和thenPing()方法来实现。示例如下:
$schedule->command('do:thing')
->daily()
->pingBefore($beforeUrl)
->thenPing($afterUrl);
若要使用这些 ping 功能,需要使用 Composer 引入 Guzzle:
"guzzlehttp/guzzle":"~5.3|~6.0"
。
任务钩子
在任务执行前后执行特定操作,可以使用
before()
和
after()
钩子。示例如下:
$schedule->command('do_thing')
->daily()
->before(function () {
// 准备操作
})
->after(function () {
// 清理操作
});
测试
在 Laravel 中测试队列作业或其他队列任务很简单。在
phpunit.xml
配置文件中,
QUEUE_DRIVER
环境变量默认设置为
sync
,这意味着测试将同步运行作业或其他队列任务,无需依赖任何队列系统。
-
检查作业是否触发
:可以使用
expectsJobs()方法来检查作业是否被触发。示例如下:
public function test_changing_number_of_subscriptions_crunches_reports()
{
$this->expectsJobs(App\Jobs\CrunchReports::class);
...
}
在 Laravel 5.3 及更高版本中,还可以使用闭包来验证已调度的作业是否符合给定条件。示例如下:
use Illuminate\
public function test_changing_subscriptions_triggers_crunch_job()
{
...
Bus::assertDispatched(CrunchReports::class, function ($e) {
return $e->subscriptions->contains(5);
});
// 也可以使用 assertNotDispatched
}
-
测试事件是否触发
:测试事件是否触发有三种方式:
- 直接测试预期的行为是否发生,而不关注事件本身。
- 明确断言事件是否触发,适用于 Laravel 5.2。示例如下:
public function test_usersubscribed_event_fires()
{
$this->expectsEvents(App\Events\UserSubscribed::class);
...
}
3. 使用闭包验证触发的事件是否符合给定条件,这是 Laravel 5.3 新增的功能。示例如下:
public function test_usersubscribed_event_fires()
{
...
Event::assertFired(UserSubscribed::class, function ($e) {
return $e->user->email = 'user-who-subscribed@mail.com';
});
// 也可以使用 assertNotFired()
}
-
禁用事件监听器
:在测试过程中,如果不想触发事件监听器,可以使用
withoutEvents()方法。示例如下:
public function test_something_subscription_related()
{
$this->withoutEvents();
...
}
常用辅助函数
Laravel 提供了许多实用的全局辅助函数,下面介绍一些常见的函数。
数组操作辅助函数
| 函数名 | 功能 | 示例 |
|---|---|---|
array_first($array, $closure, $default = null)
| 返回数组中第一个通过闭包测试的值,可设置默认值 |
$people = [
[
'email' => 'm@me.com',
'name' => 'Malcolm Me'
],
[
'email' => 'j@jo.com',
'name' => 'James Jo'
]
];
$value = array_first($people, function ($key, $person) {
return $person['email'] == 'j@jo.com';
});
|
array_get($array, $key, $default = null)
| 轻松从数组中获取值,不会因键不存在而报错,支持点符号遍历嵌套数组 |
$array = ['owner' => ['address' => ['line1' => '123 Main St.']]];
$line1 = array_get($array, 'owner.address.line1', 'No address');
$line2 = array_get($array, 'owner.address.line2');
|
array_has($array, $key)
| 检查数组是否包含特定键,支持点符号遍历嵌套数组 |
$array = ['owner' => ['address' => ['line1' => '123 Main St.']]];
if (array_has($array, 'owner.address.line2')) {
// Do stuff
}
|
array_pluck($array, $key, $indexKey)
| 返回数组中对应键的值组成的数组,可指定索引键 |
$array = [
['owner' => ['id' => 4, 'name' => 'Tricia']],
['owner' => ['id' => 7, 'name' => 'Kimberly']],
];
$array = array_pluck($array, 'owner.name');
// Returns ['Tricia', 'Kimberly'];
$array = array_pluck($array, 'owner.name', 'owner.id');
// Returns [4 => 'Tricia', 7 => 'Kimberly'];
字符串操作辅助函数
| 函数名 | 功能 | 示例 |
|---|---|---|
e($string)
|
等同于
htmlentities()
,用于安全输出字符串
|
e('<script>do something nefarious</script>');
// Returns <script>do something nefarious</script>
|
starts_with($haystack, $needle)
、
ends_with($haystack, $needle)
、
str_contains($haystack, $needle)
| 检查字符串是否以指定字符串开头、结尾或包含指定字符串 |
if (starts_with($url, 'https')) {
// Do something
}
if (ends_with($abstract, '...')) {
// Do something
}
if (str_contains($description, '1337 h4x0r')) {
// Run away
}
|
str_limit($string, $numCharacters, $concatenationString = '...')
| 限制字符串长度,超过长度可添加拼接字符串 |
$abstract = str_limit($loremIpsum, 30);
// Returns "Lorem ipsum dolor sit amet, co..."
$abstract = str_limit($loremIpsum, 30, "…");
// Returns "Lorem ipsum dolor sit amet, co…"
|
str_is($pattern, $string)
| 检查字符串是否匹配指定模式,支持通配符 |
str_is('*.dev', 'myapp.dev'); // true
str_is('*.dev', 'myapp.dev.co.uk'); // false
str_is('*dev*', 'myapp.dev'); // true
str_is('*myapp*', 'www.myapp.dev'); // true
str_is('my*app', 'myfantasticapp'); // true
str_is('my*app', 'myapp'); // true
|
str_random($length)
| 返回指定长度的随机字母数字混合大小写字符串 |
$hash = str_random(64);
|
str_slug($string, $separator = '-')
| 从字符串生成 URL 友好的 slug |
str_slug('How to Win Friends and Influence People');
// Returns 'how-to-win-friends-and-influence-people'
应用路径辅助函数
| 函数名 | 功能 | 示例 |
|---|---|---|
app_path($append = '')
| 返回应用目录的路径,可追加路径 |
app_path();
// Returns /home/forge/myapp.com/app
|
base_path($append = '')
| 返回应用根目录的路径,可追加路径 |
base_path();
// Returns /home/forge/myapp.com
|
config_path($append = '')
| 返回配置文件目录的路径,可追加路径 |
config_path();
// Returns /home/forge/myapp.com/config
|
database_path($append = '')
| 返回数据库文件目录的路径,可追加路径 |
database_path();
// Returns /home/forge/myapp.com/database
|
storage_path($append = '')
| 返回存储目录的路径,可追加路径 |
storage_path();
// Returns /home/forge/myapp.com/storage
URL 辅助函数
| 函数名 | 功能 | 示例 |
|---|---|---|
action('Controller@method’, $params = [], $absolute = true)
| 根据控制器和方法名返回正确的 URL,可传递参数,可设置是否为绝对 URL |
<a href="{{ action('PeopleController@index' }}">See all People</a>
// Returns <a href="http://myapp.com/people">See all People</a>
<a href="{{ action('PeopleController@show', ['id' => 3] }}">See Person #3</a>
// Returns <a href="http://myapp.com/people/3">See Person #3</a>
|
route($routeName, $params = [], $absolute = true)
| 根据路由名称返回 URL,可传递参数,可设置是否为绝对 URL |
<a href="{{ route('people.index') }}">See all People</a>
// Returns <a href="http://myapp.com/people">See all People</a>
<a href="{{ action('people.show', ['id' => 3]) }}">See Person #3</a>
// Returns <a href="http://myapp.com/people/3">See Person #3</a>
|
url($string)
和
secure_url($string)
| 将路径字符串转换为完整的 URL,
secure_url()
强制使用 HTTPS |
url('people/3');
// Returns http://myapp.com/people/3
|
elixir($filePath)
| 如果资产使用 Elixir 版本化系统,根据非版本化路径返回版本化文件的完整 URL |
<link rel="stylesheet" href="{{ elixir('css/app.css') }}">
// Returns something like /build/css/app-eb555e38.css
其他辅助函数
-
abort($code, $message, $headers)、abort_unless($boolean, $code, $message, $headers)、abort_if($boolean, $code, $message, $headers):用于抛出 HTTP 异常。示例如下:
public function controllerMethod(Request $request)
{
abort(403, 'You shall not pass');
abort_unless($request->has('magicToken'), 403);
abort_if($request->user()->isBanned, 403);
}
-
auth():返回 Laravel 认证器的实例,用于获取当前用户、检查登录状态等。示例如下:
$user = auth()->user();
if (auth()->check()) {
// Do something
}
-
back():生成 “重定向回上一个页面” 的响应。示例如下:
Route::get('post', function () {
...
if ($condition) {
return back();
}
});
-
collect($array):将数组转换为集合。示例如下:
$collection = collect(['Rachel', 'Hototo']);
-
config($key):返回任何点符号表示的配置项的值。示例如下:
$defaultDbConnection = config('database.default');
-
csrf_field()和csrf_token():用于在表单提交中添加 CSRF 验证。示例如下:
<form>
{{ csrf_field() }}
</form>
// or
<form>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
-
dd($variable...):用于调试,对所有参数执行var_dump()并退出应用。示例如下:
dd($var1, $var2, $state); // Why is this not working???
-
env($key, $default = null):返回给定键的环境变量值。需要注意,在配置文件之外使用env()会导致 Laravel 的某些功能不可用,建议通过配置项读取环境变量。示例如下:
$key = env('API_KEY', '');
-
dispatch($job):调度作业。示例如下:
dispatch(new EmailAdminAboutNewUser($user));
-
event($event):触发事件。示例如下:
event(new ContactAdded($contact));
-
factory($entityClass):返回给定类的工厂构建器实例。示例如下:
$contact = factory(App\Contact::class)->make();
-
old($key, $default = null):返回上一次表单提交中该表单键的值(如果存在)。示例如下:
<input name="name" value="{{ old('value', 'Your name here') }}"
-
redirect($path):返回重定向到指定路径的响应,无参数时返回Illuminate\Routing\Redirector类的实例。示例如下:
Route::get('post', function () {
...
return redirect('home');
});
-
response($body, $status, $headers):根据参数返回预构建的响应实例,无参数时返回响应工厂的实例。示例如下:
return response('OK', 200, ['X-Header-Greatness' => 'Super great']);
return response()->json(['status' => 'success'], 200);
-
view($viewPath):返回视图实例。示例如下:
Route::get('home', function () {
return view('home'); // Gets /resources/views/home.blade.php
});
集合操作
Laravel 的集合是功能强大且常被低估的工具,本质上是增强版的数组。它将数组遍历方法封装为一致、简洁、可链式调用的方法,让代码更简洁。
下面通过一个示例对比传统的
foreach
循环、PHP 原生数组函数和 Laravel 集合的使用。
-
传统
foreach循环 :
$users = [...];
$admins = [];
foreach ($users as $user) {
if ($user['status'] == 'admin') {
$user['name'] = $user['first'] . ' ' . $user['last'];
$admins[] = $user;
}
}
return $admins;
- 使用 PHP 原生数组函数 :
$users = [...];
return array_map(function ($user) {
$user['name'] = $user['first'] . ' ' . $user['last'];
return $user;
}, array_filter($users, function ($user) {
return $user['status'] == 'admin';
}));
- 使用 Laravel 集合 :
$users = collect([...]);
return $users->filter(function ($user) {
return $user['status'] == 'admin';
})->map(function ($user) {
$user['name'] = $user['first'] . ' ' . $user['last'];
return $user;
});
可以看到,使用 Laravel 集合能将复杂的操作拆分为简单、离散、易懂的任务,减少代码行数,提高代码的可读性和可维护性。例如,统计管理员数量可以这样实现:
$users = [...]
$countAdmins = collect($users)->filter(function ($user) {
return $user['status'] == 'admin'
})->count();
综上所述,Laravel 提供了丰富的功能和工具,合理运用这些功能可以大大提高开发效率和代码质量。无论是命令输出处理、测试,还是使用辅助函数和集合操作,都能让我们的开发工作更加轻松和高效。
Laravel 开发实用技巧:输出处理、测试与常用工具
集合操作进阶
Laravel 集合除了前面提到的基本操作外,还有许多其他强大的方法,下面介绍一些常用的集合方法。
常用集合方法
| 方法名 | 功能 | 示例 |
|---|---|---|
all()
| 返回集合的所有元素作为数组 |
$collection = collect([1, 2, 3]);
$array = $collection->all();
// $array 为 [1, 2, 3]
|
count()
| 返回集合中元素的数量 |
$collection = collect([1, 2, 3]);
$count = $collection->count();
// $count 为 3
|
each()
| 遍历集合中的每个元素,并对每个元素执行给定的闭包 |
$collection = collect([1, 2, 3]);
$collection->each(function ($item, $key) {
echo $item;
});
|
filter()
| 根据给定的闭包过滤集合中的元素,返回满足条件的元素组成的新集合 |
$collection = collect([1, 2, 3, 4, 5]);
$evenNumbers = $collection->filter(function ($item) {
return $item % 2 == 0;
});
// $evenNumbers 为 [2, 4]
|
map()
| 对集合中的每个元素应用给定的闭包,并返回一个新的集合,新集合中的元素是闭包的返回值 |
$collection = collect([1, 2, 3]);
$multiplied = $collection->map(function ($item) {
return $item * 2;
});
// $multiplied 为 [2, 4, 6]
|
reduce()
| 通过迭代集合中的元素,将它们合并为一个单一的值 |
$collection = collect([1, 2, 3]);
$sum = $collection->reduce(function ($carry, $item) {
return $carry + $item;
}, 0);
// $sum 为 6
|
sort()
| 对集合中的元素进行排序,返回一个新的排序后的集合 |
$collection = collect([3, 1, 2]);
$sorted = $collection->sort();
// $sorted 为 [1, 2, 3]
集合链式调用示例
集合的强大之处在于可以进行链式调用,将多个操作组合在一起。例如,我们可以先过滤出偶数,然后将这些偶数乘以 2,最后计算它们的总和。
$collection = collect([1, 2, 3, 4, 5]);
$sum = $collection->filter(function ($item) {
return $item % 2 == 0;
})->map(function ($item) {
return $item * 2;
})->reduce(function ($carry, $item) {
return $carry + $item;
}, 0);
// $sum 为 12
实际应用场景
下面通过几个实际的应用场景,展示如何在 Laravel 开发中使用前面介绍的知识。
任务调度与监控
假设我们有一个定时任务,需要每天凌晨 2 点执行,并且要将任务的输出保存到文件中,同时在任务执行前后进行 HTTP “ping” 监控。
$schedule->command('do:thing')
->dailyAt('02:00')
->appendOutputTo($filePath)
->pingBefore($beforeUrl)
->thenPing($afterUrl);
在这个示例中,
dailyAt('02:00')
表示任务每天凌晨 2 点执行,
appendOutputTo($filePath)
用于将任务输出追加到指定文件,
pingBefore($beforeUrl)
和
thenPing($afterUrl)
用于在任务执行前后进行 HTTP “ping” 监控。
数据处理与展示
假设我们有一个用户列表,需要过滤出管理员用户,并将他们的姓名显示在页面上。
$users = collect([
['name' => 'John', 'status' => 'admin'],
['name' => 'Jane', 'status' => 'user'],
['name' => 'Bob', 'status' => 'admin']
]);
$adminNames = $users->filter(function ($user) {
return $user['status'] == 'admin';
})->map(function ($user) {
return $user['name'];
});
foreach ($adminNames as $name) {
echo $name . '<br>';
}
在这个示例中,我们首先使用
filter()
方法过滤出管理员用户,然后使用
map()
方法提取他们的姓名,最后遍历显示这些姓名。
表单验证与 CSRF 保护
在 Laravel 中,表单验证和 CSRF 保护是非常重要的。下面是一个简单的表单示例,展示如何使用
csrf_field()
和
old()
函数。
<form method="post" action="/submit">
{{ csrf_field() }}
<input type="text" name="name" value="{{ old('name', 'Your name here') }}">
<input type="submit" value="Submit">
</form>
在这个示例中,
{{ csrf_field() }}
用于在表单中添加 CSRF 令牌,
old('name', 'Your name here')
用于在表单提交失败时,保留用户之前输入的值。
总结与展望
Laravel 作为一个强大的 PHP 框架,提供了丰富的功能和工具,无论是任务调度、测试,还是数据处理和表单验证,都能让开发者更加轻松地完成开发任务。通过合理运用 Laravel 的辅助函数和集合操作,我们可以提高代码的可读性、可维护性和开发效率。
在未来的开发中,我们可以进一步探索 Laravel 的其他功能,如数据库迁移、模型关联、中间件等,以构建更加复杂和强大的应用程序。同时,我们也可以结合前端框架,如 Vue.js 或 React.js,实现前后端分离的开发模式,提高应用的性能和用户体验。
总之,掌握 Laravel 的开发技巧,能够让我们在 PHP 开发领域更加游刃有余,为我们的职业生涯带来更多的机会和挑战。
流程图:集合操作流程
graph LR
A[创建集合] --> B[过滤元素]
B --> C[映射元素]
C --> D[合并元素]
D --> E[输出结果]
这个流程图展示了一个典型的集合操作流程,从创建集合开始,经过过滤、映射和合并等操作,最终输出处理后的结果。在实际开发中,我们可以根据具体的需求,灵活组合这些操作,实现复杂的数据处理任务。
通过本文的介绍,相信你对 Laravel 的命令输出处理、测试、辅助函数和集合操作有了更深入的了解。希望这些知识能够帮助你在 Laravel 开发中更加高效地完成任务,提升你的开发技能和水平。
超级会员免费看
1059

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



