php的option,PHP Option - 一个可选的类型库

PHP Option Type 5df75d1206393fad23194f7bbda84a32.png68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f7363686d6974746a6f682f7068702d6f7074696f6e2f6261646765732f7175616c6974792d73636f72652e706e673f733d37666562306663633531353062333632313666373638333239326564383438306161623136323862

This adds an Option type for PHP.

The Option type is intended for cases where you sometimes might return a value (typically an object), and sometimes you might return no value (typically null) depending on arguments, or other runtime factors.

Often times, you forget to handle the case where no value is returned. Not intentionally of course, but maybe you did not account for all possible states of the system; or maybe you indeed covered all cases, then time goes on, code is refactored, some of these your checks might become invalid, or incomplete. Suddenly, without noticing, the no value case is not handled anymore. As a result, you might sometimes get fatal PHP errors telling you that you called a method on a non-object; users might see blank pages, or worse.

On one hand, the Option type forces a developer to consciously think about both cases (returning a value, or returning no value). That in itself will already make your code more robust. On the other hand, the Option type also allows the API developer to provide more concise API methods, and empowers the API user in how he consumes these methods.

Installation

Installation is super-easy via composer

composer require phpoption/phpoption

or add it to your composer.json file.

Usage

Using the Option Type in your API

class MyRepository

{

public function findSomeEntity($criteria)

{

if (null !== $entity = $this->em->find(...)) {

return new \PhpOption\Some($entity);

}

// We use a singleton, for the None case.

return \PhpOption\None::create();

}

}

If you are consuming an existing library, you can also use a shorter version which by default treats null as None, and everything else as Some case:

class MyRepository

{

public function findSomeEntity($criteria)

{

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);

}

}

Case 1: You always Require an Entity in Calling Code

$entity = $repo->findSomeEntity(...)->get(); // returns entity, or throws exception

Case 2: Fallback to Default Value If Not Available

$entity = $repo->findSomeEntity(...)->getOrElse(new Entity());

// Or, if you want to lazily create the entity.

$entity = $repo->findSomeEntity(...)->getOrCall(function() {

return new Entity();

});

More Examples

No More Boiler Plate Code

// Before

if (null === $entity = $this->findSomeEntity()) {

throw new NotFoundException();

}

echo $entity->name;

// After

echo $this->findSomeEntity()->get()->name;

No More Control Flow Exceptions

// Before

try {

$entity = $this->findSomeEntity();

} catch (NotFoundException $ex) {

$entity = new Entity();

}

// After

$entity = $this->findSomeEntity()->getOrElse(new Entity());

More Concise Null Handling

// Before

$entity = $this->findSomeEntity();

if (null === $entity) {

return new Entity();

}

return $entity;

// After

return $this->findSomeEntity()->getOrElse(new Entity());

Trying Multiple Alternative Options

If you'd like to try multiple alternatives, the orElse method allows you to do this very elegantly:

return $this->findSomeEntity()

->orElse($this->findSomeOtherEntity())

->orElse($this->createEntity());

The first option which is non-empty will be returned. This is especially useful with lazy-evaluated options, see below.

Lazy-Evaluated Options

The above example has the flaw that we would need to evaluate all options when the method is called which creates unnecessary overhead if the first option is already non-empty.

Fortunately, we can easily solve this by using the LazyOption class:

return $this->findSomeEntity()

->orElse(new LazyOption(array($this, 'findSomeOtherEntity')))

->orElse(new LazyOption(array($this, 'createEntity')));

This way, only the options that are necessary will actually be evaluated.

Performance Considerations

Of course, performance is important. Attached is a performance benchmark which you can run on a machine of your choosing.

The overhead incurred by the Option type comes down to the time that it takes to create one object, our wrapper. Also, we need to perform one additional method call to retrieve the value from the wrapper.

Overhead: Creation of 1 Object, and 1 Method Call

Average Overhead per Invocation (some case/value returned): 0.000000761s (that is 761 nano seconds)

Average Overhead per Invocation (none case/null returned): 0.000000368s (that is 368 nano seconds)

The benchmark was run under Ubuntu precise with PHP 5.4.6. As you can see the overhead is surprisingly low, almost negligible.

So in conclusion, unless you plan to call a method thousands of times during a request, there is no reason to stick to the object|null return value; better give your code some options!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值