imanghafoori/laravel-nullable

一个帮助您以函数式方式编写表达性防御性代码的包

v1.2.9 2024-01-24 03:54 UTC

This package is auto-updated.

Last update: 2024-09-24 05:45:59 UTC


README

不要让 "null" 伪装你的对象。

StyleCI Quality Score Code Coverage Latest Stable Version PHP from Packagist License

在 Laravel 中使用函数式编程范式

用 ❤️ 为每个聪明的 Laravel 开发者构建

Null 通常用来表示缺失的值(例如,当我们找不到具有特定 Id 的行时,我们返回 null),这是一个坏主意,我们将消灭它!!!

🔥 安装

composer require imanghafoori/laravel-nullable

此包公开了一个全局辅助函数 nullable(),您可以用它来包装变量,这些变量有时是对象,有时是 null

考虑这个

$email = TwitterApi::find(1)->email;

现在这段代码运行正常,但是...

如果将来用户 ID 为 1 的用户被删除怎么办?!

null->email 和垃圾!😧

所以,如果你忘记用 if 语句处理 null,你会遇到错误。

你需要一些东西来强迫你和你所在类方法的用户处理 null 的情况。

为了防止此类错误,你应该这样编写代码

$user = $twitterApi->find($id);

if ($user === null) {
    return redirect()->route('page_not_found');
}

▶️ 可空对象来拯救!!!

要重构上面的代码,首先

你必须更改你的 repo 类

// the old way:

/**
* @return User|null            <---- consider here. We are returning two types !!!
*/
public function find ($id) {
     $user = TwitterApi::search($id);
     
     if (!$user) {
         return null;
     }
     return new User($user);   
}

上面的代码返回两种类型,这是方法调用者困惑的来源。他们准备好了一种类型,忘记了另一种。

让我们对它做一些小的改动

/**
 * @return Nullable        <---- we now have only one consistent type. Not two.
 */
public function find ($id) {
     $user = TwitterApi::search($id);
     
     if (!$user) {
         return new Nullable(null);   //  <----  instead of pure null;
     }
     $user = new User($user);   
     
     $message = 'Model Not Found with Id : '. $id;

     return new Nullable($user, [$message]);   //  <----  instead of User;
}

🔔 现在我们的方法始终返回可空对象,不管是什么:

在这个改动之后,没有人可以访问你的 repo 的真实内容(在这个例子中是用户对象),除非他/她提供了一种处理 null 的情况的方法。不需要 if(is_null()),不需要异常处理。

记住,PHP 不会强迫我们写那个 if,而我们作为人类总是倾向于忘记它。

这就是区别!在之前,很容易忘记,但现在如果你忘记了,你就无法继续!!!

$userObj = $userRepo->find($id)->getOrSend(function ($message) {

  return redirect()->route('page_not_found')->with('error', $message);
});

// Call a static method.
$userObj = $twitterApi->find($id)->getOrSend([Response::class, 'pageNotFound']);

// or a get default value
$userObj = $twitterApi->find($id)->getOr(new User());

现在我们可以确定 $user 不会为 null,我们可以安心地睡觉了!

▶️ 测试

另一个优点是,如果你使用可空对象并且忘记编写模拟返回 null 值的情况的测试,phpunit 代码覆盖率会突出显示你传递给 ->getOrDo()(或类似方法)的闭包,将其标记为未覆盖,表明存在缺失的测试。

但是,如果你直接返回对象,你可以在没有覆盖 nully 情况的测试的情况下获得 100% 的代码覆盖率,因此隐藏的错误可能仍然潜伏在 100% 的覆盖率下。

▶️ 常见问题解答

为什么抛出异常并不总是最好的主意?

当你抛出异常时,你应该始终问自己。是否有任何人在那里等待捕获它??如果他们忘记捕获和处理异常怎么办??这与 null 是同样的问题。它会导致错误。

关键是如果他们忘记处理失败,就没有继续的途径。

更多来自作者

Laravel 中间件(新**)

💎 你可以在任何方法调用上添加中间件。

Laravel Hey Man

💎 它允许编写表达式代码来授权、验证和身份验证。

Laravel 终结者

💎 一个最小化但功能强大的包,为您提供重构控制器的机会。

Laravel 任意密码登录

💎 它允许您仅在本地环境中使用任何密码登录。

Eloquent 相对性

💎 它允许您解耦 Eloquent 模型,以实现模块化结构。