imanghafoori / laravel-nullable
一个帮助您以函数式方式编写表达性防御性代码的包
Requires
- php: ^7.1.3|7.2.*|7.3.*|7.4.*|8.0.*|8.1.*|8.2.*|8.3.*
- laravel/framework: ~5.1|6.*|7.*|8.*|9.*|10.*|11.*
Requires (Dev)
- mockery/mockery: ^1.0
- orchestra/testbench: ~4.0
Suggests
- imanghafoori/laravel-anypass: Allows you login with any password in local environment.
- imanghafoori/laravel-decorator: Allows you to easily apply the decorator pattern in a laravel app.
- imanghafoori/laravel-masterpass: You can easily set a master password without code change.
- imanghafoori/laravel-terminator: Gives you opportunity to refactor your controllers.
- imanghafoori/laravel-widgetize: Gives you a better structure and caching opportunity for your web pages.
README
不要让 "null" 伪装你的对象。
在 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 模型,以实现模块化结构。