phpoption / phpoption
PHP的选项类型
Requires
- php: ^7.2.5 || ^8.0
Requires (Dev)
- bamarni/composer-bin-plugin: ^1.8.2
- phpunit/phpunit: ^8.5.39 || ^9.6.20 || ^10.5.28
README
本包实现了PHP的选项类型!
动机
选项类型旨在处理在某些情况下可能会返回值(通常是对象),而在其他情况下可能会根据参数或其他运行时因素返回基本值(通常是null)的情况。
很多时候,你会忘记处理返回基本值的情况。当然不是故意的,但可能你没有考虑到所有可能的状态;或者你可能确实覆盖了所有情况,随着时间的推移,代码被重构,其中一些检查可能变得无效或不完整。突然之间,没有注意到,基本值的情况不再被处理了。结果,有时你可能会收到致命的PHP错误,告诉你对一个非对象调用了方法;用户可能会看到空白页,或者更糟。
一方面,选项类型迫使开发者有意识地考虑这两种情况(返回值或返回基本值)。这本身就会让你的代码更加健壮。另一方面,选项类型还允许API开发者提供更简洁的API方法,并赋予API用户如何消费这些方法的权力。
安装
通过 Composer 安装非常简单
$ composer require phpoption/phpoption
或者手动添加到你的 composer.json
文件中。
用法
在API中使用选项类型
class MyRepository { public function findSomeEntity($criteria): \PhpOption\Option { if (null !== $entity = $this->em->find(...)) { return new \PhpOption\Some($entity); } // We use a singleton, for the None case. return \PhpOption\None::create(); } }
如果你正在使用现有的库,你也可以使用一个简短的版本,默认将 null
视为 None
,将其他所有内容视为 Some
情况
class MyRepository { public function findSomeEntity($criteria): \PhpOption\Option { return \PhpOption\Option::fromValue($this->em->find(...)); // or, if you want to change the none value to false for example: return \PhpOption\Option::fromValue($this->em->find(...), false); } }
案例1:在调用代码中始终需要实体
$entity = $repo->findSomeEntity(...)->get(); // returns entity, or throws exception
案例2:如果不可用则回退到默认值
$entity = $repo->findSomeEntity(...)->getOrElse(new Entity()); // Or, if you want to lazily create the entity. $entity = $repo->findSomeEntity(...)->getOrCall(function() { return new Entity(); });
更多示例
不再有样板代码
// Before $entity = $this->findSomeEntity(); if (null === $entity) { throw new NotFoundException(); } echo $entity->name; // After echo $this->findSomeEntity()->get()->name;
不再有控制流异常
// Before try { $entity = $this->findSomeEntity(); } catch (NotFoundException $ex) { $entity = new Entity(); } // After $entity = $this->findSomeEntity()->getOrElse(new Entity());
更简洁的null处理
// Before $entity = $this->findSomeEntity(); if (null === $entity) { return new Entity(); } return $entity; // After return $this->findSomeEntity()->getOrElse(new Entity());
尝试多个替代选项
如果你想尝试多个替代方案,可以使用 orElse
方法,这可以非常优雅地完成
return $this->findSomeEntity() ->orElse($this->findSomeOtherEntity()) ->orElse($this->createEntity());
将返回第一个非空的选项。这在与延迟评估选项一起使用时尤其有用。
延迟评估选项
上面的例子有一个缺点,即我们需要在方法调用时评估所有选项,这会创建不必要的开销,如果第一个选项已经非空。
幸运的是,我们可以通过使用 LazyOption
类轻松解决这个问题
return $this->findSomeEntity() ->orElse(new LazyOption(array($this, 'findSomeOtherEntity'))) ->orElse(new LazyOption(array($this, 'createEntity')));
这样,只有必要的选项才会实际被评估。
性能考虑
当然,性能很重要。附带的性能基准测试可以在你选择的机器上运行。选项类型带来的开销是创建一个对象,我们的包装器,以及一个额外的调用包装器以检索值的方法所需的时间。除非你打算在请求期间多次调用方法,否则没有理由坚持使用 object|null
返回值;最好给你的代码一些选择!
安全
如果在包中发现安全漏洞,请发送电子邮件至 security@tidelift.com。我们将及时处理所有安全漏洞。您可以在这里查看我们的完整安全策略。
许可证
PHP Option Type 使用 Apache License 2.0 许可。
企业版
作为 Tidelift 订阅的一部分提供
phpoption/phpoption
的维护者以及成千上万的其他包维护者正在与 Tidelift 合作,为您提供构建应用程序所使用的开源依赖的商业支持和维护。节省时间,降低风险,并提高代码质量,同时支付您所使用的确切依赖的维护者。了解更多信息点击这里。