戏里戏外

在 Laravel 中避免 if 语句

2024-10-31#Laravel

Laravel 中一些便捷的辅助函数和方法,帮助开发者简化代码中的判断逻辑。

throw_ifthrow_unless

当需要根据条件引发异常时,则可能会编写类似此类 if 条件判断:

<?php

if ($user->inactive()) {
    throw new InactiveUserException();
}

if (!$user->active()) {
    throw new InactiveUserException();
}

Laravel 5.5 起提供了两个辅助函数 throw_ifthrow_unless,它们可以快速调用上面的 if 语句。

<?php

throw_if($user->inactive(), new InactiveUserException());

throw_unless($user->active(), new InactiveUserException());

abort_ifabort_unless

在业务逻辑中需要使用 abort 抛出错误。

if ($user->inactive()) {
    abort(403, 'Unauthorized', []);
}

使用 abort_ifabort_unless 函数将逻辑减少到一行。

abort_if($user->inactive(), 403);

abort_unless($user->active(), 403);

optional

从 PHP 8.0 开始引入了 nullsafe 运算符 能优化 if 条件判断。

如果使用的是较旧的 PHP 版本,可以使用 optional 函数

假设需要访问用户的国家/地区名称,但知道国家/地区的关联关系可能不存在。

if ($user->country) {
    $country = $user->country->name;
}

使用 optional 函数更优雅的解决这个问题。

$country = optional($user->country)->name;

# 如果用户也可能不可
$country = optional(optional($user)->country)->name;

# PHP >= 8.0
$country = $user?->country?->name;

使用 PHP 8.0 的 nullsafe 运算符会让代码变得更简洁。

firstOrCreate

当记录不存在时才将记录插入数据库,可能会编写如下代码逻辑。

if (!Visit::whereIp(request()->ip())->count()) {
    Visit::create([
        'ip' => request()->ip()
    ]);
}

在示例中,如果已存在具有相同 IP 地址的记录,则确保不会记录两次。

更好的方法是使用 firstOrCreate 该方法。

$visit = Visit::firstOrCreate(['ip' => request()->ip()], [
    'ip' => request()->ip()
]);
Tip
  • 第一个数组参数是要检查的唯一列
  • 第二个数组参数是要写入的数据

如果需要根据模型判断是否已创建可以在返回的模型上使用 wasRecentlyCreated 属性。

其他类似的方法也存在(firstOrNewupdateOrCreatefindOrNew 等)。

whenunlesswhenEmptywhenNotEmpty

Laravel 的 ModelCollection 类都包含根据条件在闭包内执行操作的方法。

模型

Eloquent 模型上使用 Conditionable Trait。

删除用户账户(如果计划删除用户)的示例。

if ($user->scheduledForDeletion()) {
    $user->delete();
}

在模型上使用 whenunless 该方法。

$user->when($user->scheduledForDeletion(), fn ($user) => $user->delete());

$user->unless(!$user->scheduledForDeletion(), fn ($user) => $user->delete());

集合

集合上使用 EnumeratesValues Trait。

包含 whenwhenEmptywhenNotEmpty 方法。

if ($users->count() === 100) {
    $newlyRegisteredUser->awardPrize();
}

$users 是用户的集合,可以使用 when 代替 if 语句。

$users->when($users->count() === 100, fn ($users) => $newlyRegisteredUser->awardPrize());

firstOrFail

当需要通过查询模型查询数据,在找不到模型时抛出 404。

if (!$plan = Plan::whereStripeId($request->stripe_id)->first()) {
    throw new NotFoundHttpException();
}

在示例中按计划的 Stripe ID 查找计划,如果条件成功抛出 NotFoundHttpException 来呈现 404 页面。

可以使用 firstOrFail 来为您完成所有这些操作。

$plan = Plan::whereStripeId($request->stripe_id)->firstOrFail();