mkjpryor/option

为PHP提供的简单选项和结果类型

dev-master 2015-03-31 15:23 UTC

This package is not auto-updated.

Last update: 2024-09-24 03:33:44 UTC


README

PHP的简单选项和结果类,受Scala的Option、Haskell的Maybe和Rust的Result启发。

Option类型在处理可能存在或不存在值的操作时,提供了比可空类型额外的功能。

Result类型还包括失败的原因(异常),允许错误在不担心特定处理的情况下传播。

安装

可以通过Composer安装mkjpryor/option

php composer.phar require mkjpryor/option dev-master

用法

创建Option或Result

<?php

use Mkjp\Option\Option;
use Mkjp\Option\Result;

// Creates a non-empty option containing the value 10
$o1 = Option::just(10);

// Creates an empty option
$o2 = Option::none();

// Creates an option from a nullable value
//   If null is given, an empty option is created
$o3 = Option::from(10);
$o3 = Option::from(null);

// Create a successful result with the given value
$r1 = Result::success(42);

// Create an errored result with the given error
$r2 = Result::error(new \Exception("Some error occurred"));

// Create a result by trying some operation that might fail
//   Creates a success if the function returns successfully
//   Creates an error if the function throws an exception
$r3 = Result::_try(function() {
    // Some operation that might fail with an exception
});

从Option或Result中检索值

可以从Option中以不安全或安全的方式检索底层值

<?php

// UNSAFE - throws a LogicException if the option is empty
$val = $option->get();

// Returns the option's value if it is non-empty, 0 otherwise
$val = $option->getOrDefault(0);  

// Returns the option's value if it is non-empty, otherwise the result of evaluating the given function
//   Useful if the default value is expensive to compute
$val = $option->getOrElse(function() { return 0; });  

// Return the option's value if it is non-empty, null otherwise
$val = $option->getOrNull();

类似地,可以通过不安全或安全的方式检索Result的底层值(或错误)

<?php

// UNSAFE - if the result is an error, the exception that caused the error is thrown
$val = $result->get();

// UNSAFE - if the result is a success, a LogicException is thrown
$err = $result->getError();

// Returns the result's value if it is a success, 0 if it is an error
$val = $result->getOrDefault(0);

// Returns the result's value if it is a success, otherwise the result of evaluating
// the given function with the exception that caused the error
//   Useful if the default value is expensive to compute or depends on the type of error
$val = $result->getOrElse(function(\Exception $error) {
    if( $error instanceof MyException ) return 0;
    return -1;
});  

// Return the result's value if it is a success, null otherwise
$val = $result->getOrNull();

操作选项和结果

OptionResult有几种方法可以安全地操作,例如mapfilter。请参阅代码以获取更多详细信息。

示例

在以下示例中,我们想要从数据库中通过id检索一个用户并欢迎他们。如果用户不存在,我们希望欢迎他们作为客人。

<?php

use Mkjp\Option\Option;
use Mkjp\Option\Result;


/**
 * Simple user class
 */
class User {
    public $id;
    public $username;
    public function __construct($id, $username) {
        $this->id = $id;
        $this->username = $username;
    }
}

/**
 * Fetches a user from a database by their id
 *
 * Note how we return a Result containing an Option
 * This is because there are three possible outcomes that are semantically different:
 *   1. We successfully find a user
 *   2. The user doesn't exist in the database (this isn't an error - it is expected and must be handled)
 *   3. There is an error querying the database
 */
function findUserById($id) {
    // Assume DB::execute throws a DBError if there is an error while querying
    $result = Result::_try(function() use($id) {
        return DB::execute("SELECT * FROM users WHERE id = ?", $id);
    });
    
    // Use the error propagation to our advantage
    return $result->map(function($data) {
        if( count($data) > 0 ) {
            return Option::just(new User($data[0]["id"], $data[0]["username"]));
        }
        else {
            return Option::none();
        }
    });
}

$id = 1234;  // This would come from request params or something similar
    
// Print an appropriate welcome message for the user
echo "Hello, " . findUserById($id)
                     // In this case, treat a DB error like not finding a user
                     //
                     // toOption converts the Result<Option<User>> into an
                     // Option<Option<User>>, which we flatten to an Option<User>
                     ->toOption()->flatten()
                     // Get the username from the user
                     ->map(function($u) { return $u->username; })
                     // If we didn't find a user, use a default name
                     ->getOrDefault("Guest");

许可证

此代码根据MIT许可证的条款进行许可。