phpoption/phpoption

PHP的选项类型

资助包维护!
GrahamCampbell
Tidelift

安装次数: 368,849,038

依赖: 159

建议者: 2

安全: 0

星标: 2,608

关注者: 26

分支: 63

开放问题: 3

1.9.3 2024-07-20 21:41 UTC

README

本包实现了PHP的选项类型!

Banner

Software License Total Downloads Latest Version

动机

选项类型旨在处理在某些情况下可能会返回值(通常是对象),而在其他情况下可能会根据参数或其他运行时因素返回基本值(通常是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 合作,为您提供构建应用程序所使用的开源依赖的商业支持和维护。节省时间,降低风险,并提高代码质量,同时支付您所使用的确切依赖的维护者。了解更多信息点击这里