• Stars
    star
    2,598
  • Rank 17,638 (Top 0.4 %)
  • Language
    PHP
  • License
    Apache License 2.0
  • Created about 12 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Option Type for PHP

PHP Option Type

This package implements the Option type for PHP!

Banner

Software License Total Downloads Latest Version

Motivation

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

Often times, you forget to handle the case where a base value should be 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 base 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 a base 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 by hand to your composer.json file.

Usage

Using the Option Type in your 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();
    }
}

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): \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);
    }
}

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
$entity = $this->findSomeEntity();
if (null === $entity) {
    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, and one additional method call to retrieve the value from the wrapper. 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!

Security

If you discover a security vulnerability within this package, please send an email to [email protected]. All security vulnerabilities will be promptly addressed. You may view our full security policy here.

License

PHP Option Type is licensed under Apache License 2.0.

For Enterprise

Available as part of the Tidelift Subscription

The maintainers of phpoption/phpoption and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

More Repositories

1

serializer

Library for (de-)serializing data of any complexity (supports JSON, and XML)
PHP
2,325
star
2

JMSSerializerBundle

Easily serialize, and deserialize data of any complexity (supports XML, JSON, YAML)
PHP
1,800
star
3

metadata

Metadata is a library for metadata management in PHP
PHP
1,790
star
4

php-collection

General Purpose Collection Library for PHP
PHP
975
star
5

parser-lib

Library for Writing Recursive-Descent Parsers
PHP
835
star
6

JMSTranslationBundle

Puts the Symfony2 Translation Component on steroids
PHP
427
star
7

JMSI18nRoutingBundle

Allows you to internationalize your routing
PHP
358
star
8

twig.js

twig.js, flexible, secure, and high-performance templating engine for Javascript
PHP
357
star
9

JMSJobQueueBundle

Run and Schedule Symfony Console Commands as Background Jobs
PHP
335
star
10

JMSDiExtraBundle

Provides Advanced Dependency Injection Features for Symfony2
PHP
330
star
11

JMSSecurityExtraBundle

Enhances the Symfony2 Security Component with several new features
PHP
255
star
12

JMSAopBundle

Adds AOP capabilities to Symfony
PHP
200
star
13

JMSPaymentCoreBundle

A unified API for processing payments with Symfony
PHP
194
star
14

JMSDebuggingBundle

This bundle provides advanced debugging tools for your Symfony2 project.
PHP
161
star
15

cg-library

Provides a toolset for generating PHP code
PHP
157
star
16

JMSPaymentPaypalBundle

Payment Bundle providing access to the PayPal API
PHP
122
star
17

php-manipulator

Library for Analyzing and Modifying PHP Source Code
PHP
106
star
18

JMSTwigJsBundle

Integrates twig.js into your Symfony2 application
PHP
79
star
19

composer-deps-analyzer

Library for Analyzing Dependencies of composer projects
PHP
59
star
20

php-stubs

Stubs for PHP core and third-party extensions for auto-completion, or static analysis
PHP
58
star
21

object-routing

Library for generating routes based on objects.
PHP
56
star
22

JMSCommandBundle

Provides useful commands to ease development with Symfony2.
PHP
43
star
23

php-code-analysis

Advanced Code Analysis for PHP
24
star
24

JMSGoogleClosureBundle

Eases development with the Google Closure Tools in Symfony2
JavaScript
21
star
25

jmsPaymentPlugin

A payment plugin for the symfony framework based on Doctrine 1.2
PHP
10
star
26

build-artifact-uploader

Uploads Build Artifacts from a CI Server (such as Travis)
PHP
4
star
27

JMSRstBundle

This bundle is not intended for re-use. Use at your own risk.
PHP
3
star
28

php-debugger

not ready yet
PHP
3
star
29

JMSFormExtraBundle

This bundle is not intended for re-use. Use at your own risk.
PHP
3
star
30

jmsFormsPlugin

This plugin provides several enhancements to symfony's form framework.
PHP
3
star
31

plovr

This is only a fork since the original project is not hosted on GitHub, see its official homepage
JavaScript
2
star
32

jmsDoctrinePlugin

Provides some useful templates for Doctrine 1.2, and some enhancements overall
PHP
2
star
33

JMSSupportBundle

This bundle is not intended for re-use. Use at your own risk.
PHP
1
star
34

commons.js

JavaScript
1
star
35

JMSCrmBundle

This bundle is not intended for re-use. Use at your own risk.
PHP
1
star
36

JMSAwsBundle

This bundle is not intended for re-use. Use at your own risk.
PHP
1
star
37

JMSSocialBundle

This bundle is not intended for re-use. Use at your own risk.
PHP
1
star