stygian91 / php-cordyceps
0.3.0
2024-06-16 08:44 UTC
Requires
- php: ^7.4 || ^8.1
Requires (Dev)
- phpunit/phpunit: ^9
README
Cordyceps 是一个小型包,提供了两个主要的类:用于处理 null 值的 Option
和用于处理错误的 Result
。
Option
Option
是一个包装可能为 null 的值的包装器,这允许我们在每次可能返回 null 值的操作之后减少需要执行的 null 检查次数。在我们完成所有的操作之后,我们才需要解包内部值并检查它是否确实存在。
示例
<?php // this: function myFunc($arg) { $value1 = somethingThatCouldBeNull1($arg); if (is_null($value1)) { return null; } $value2 = somethingThatCouldBeNull2($value1); if (is_null($value2)) { return null; } $value3 = somethingThatCouldBeNull3($value2); if (is_null($value3)) { return null; } // use $value3 } // ------------ // becomes this: function myFunc2($arg) { $option = Option::make(somethingThatCouldBeNull1($arg)) // Any callable works here, you can pass regular functions, anon functions and class methods // the same way you'd pass them to `call_user_func_array`. ->map('somethingThatCouldBeNull2') ->map('somethingThatCouldBeNull3') ->map(function ($value) { // use final $value }); // At the end you *will* need to unwrap the value to see if the chain succeeded. // You can query if the wrapped value is "something" or "nothing" with $option->isSome() and $option->isNone(). // $option->unwrap() will return the wrapped value, be it null or not. // If you want to provide a fallback value, you can use $option->unwrapOr($fallback). // You can also lazily evaluate the fallback value by using $option->unwrapOrElse(fn () => 'fallback value'). }
Result
Result
是一个包装器,使将错误作为值处理变得更加容易。这是 try/catch 的替代方案,将错误作为值处理的主要好处是,当真正解包可能成为您的“绿色路径”值或错误的值时,您会提醒自己操作可能会失败。而忘记进行 try/catch 非常容易。
示例
<?php // this: function thisCouldGoWrong1($arg) { // ... if (somethingIsWrong($arg)) { throw new Exception('oops'); } return 'some value'; } function thisCouldGoWrong2($arg) { // ... if (somethingIsWrong2($arg)) { throw new Exception('oops 2'); } return 'some value 2'; } try { $res = thisCouldGoWrong1(42); $res = thisCouldGoWrong2($res); } catch (\Throwable $th) { // handle error } // ------------ // becomes this: function thisCouldGoWrong1($arg) { // ... if (somethingIsWrong($arg)) { return Result::makeErr(new Exception('oops')); } return Result::makeOk('some value'); } function thisCouldGoWrong2($arg) { // ... if (somethingIsWrong($arg)) { return Result::makeErr(new Exception('oops 2')); } return Result::makeOk('some value 2'); } $res = thisCouldGoWrong1(42) // just like Option, you can pass anything that would fit in `call_user_func_array` ->andThen('thisCouldGoWrong2'); if ($res->isErr()) { $exception = $res->unwrap(); // handle the exception } else { $value = $res->unwrap(); } // or if you want, you can provide a fallback value, like you can with option: $value = $res->unwrapOr('fallback'); // or lazily-evaluated version: $value = $res->unwrapOrElse(fn () => 'fallback');
这对于我们的代码来说都很好,但是当我们不得不调用旧代码或第三方代码,这些代码会抛出异常时,我们该怎么办呢?您可以使用 Result::try()
将可能抛出异常的可调用包装起来。
示例
<?php // Result::try's arguments are the same as call_user_func_array $res = Result::try('thisCouldThrow', ['func arg', 'func arg 2']); if ($res->isErr()) { // handle error }