Last active
August 29, 2015 14:04
-
-
Save ciarand/16477db954760a4b98d0 to your computer and use it in GitHub Desktop.
Playing around with creating an intuitive API for Result-type objects (i.e. Failure / Success wrappers) and their interactions w/ Exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
abstract class Result | |
{ | |
public static function fromValue($value, $reject = null) | |
{ | |
return ($value !== $reject) ? new Success($value) : new Failure; | |
} | |
public static function failOnException($callback) | |
{ | |
return function ($value) use ($callback) { | |
try { | |
return new Success(call_user_func($callback, $value)); | |
} catch (Exception $e) { | |
return new Failure($e->getMessage()); | |
} | |
}; | |
} | |
abstract public function get(); | |
abstract public function failIf($value); | |
abstract public function resultOf(callable $callable); | |
abstract public function filter(callable $callable, $message = ""); | |
abstract public function orThrow($type, $message = ""); | |
} | |
class Success extends Result | |
{ | |
private $value; | |
public function __construct($value) | |
{ | |
$this->value = $value; | |
} | |
public function get() | |
{ | |
return $this->value; | |
} | |
public function failIf($value) | |
{ | |
if ($this->value === $value) { | |
return new Failure; | |
} | |
return $this; | |
} | |
public function resultOf(callable $callable) | |
{ | |
return call_user_func($callable, $this->value); | |
} | |
public function filter(callable $filter, $message = "") | |
{ | |
return call_user_func($filter, $this->value) ? $this : new Failure($message); | |
} | |
public function orThrow($type, $message = "") | |
{ | |
return $this; | |
} | |
} | |
class Failure extends Result | |
{ | |
private $message; | |
public function __construct($message = "") | |
{ | |
$this->message = $message; | |
} | |
public function filter(callable $filter, $message = "") | |
{ | |
return $this; | |
} | |
public function failIf($value) | |
{ | |
return $this; | |
} | |
public function resultOf(callable $callable) | |
{ | |
return $this; | |
} | |
public function orThrow($type, $message = "") | |
{ | |
throw new $type($message ?: $this->message); | |
} | |
public function get() | |
{ | |
throw new RuntimeException("idk"); | |
} | |
} | |
/** | |
* Dummy filters and callables and stuff | |
*/ | |
class InputIsValidFilter | |
{ | |
public function __invoke($input) | |
{ | |
if (intval($input) % 2 === 1) { | |
return new Success($input); | |
} | |
return new Failure("input wasn't odd"); | |
} | |
} | |
class Database | |
{ | |
public static function persist($data) | |
{ | |
if ($data === 7) { | |
throw new Exception("some sort of DB error"); | |
} | |
return $data; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php require "result.php"; | |
return function ($input) { | |
Result::fromValue($input->whatever) | |
->failIf("") | |
->orThrow("InvalidArgumentException", "No data passed") | |
->resultOf(new InputIsValidFilter) | |
->orThrow("InvalidArgumentException") | |
->resultOf(Result::failOnException("Database::persist")) | |
->orThrow("RuntimeException"); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$routine = require "routine.php"; | |
// ////////////////////// // | |
// boring print utilities // | |
// ////////////////////// // | |
$print = function ($attempt, $msg) { | |
$type = gettype($attempt); | |
echo "Attempt with {$type} \"{$attempt}\": {$msg}" . PHP_EOL; | |
}; | |
$printSuccess = function ($attempt) use ($print) { | |
echo $print($attempt, "succeeded"); | |
}; | |
$printFailure = function ($attempt, Exception $error) use ($print) { | |
echo $print($attempt, "failed with error {$error->getMessage()}"); | |
}; | |
// ///////// // | |
// test loop // | |
// ///////// // | |
$data = [1, "", 2, 3, 7, "a string", 7 * 3, 211, "whatever"]; | |
foreach ($data as $attempt) { | |
try { | |
$routine((object) ["whatever" => $attempt]); | |
$printSuccess($attempt); | |
} catch (Exception $e) { | |
$printFailure($attempt, $e); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment