Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2af48ed

Browse files
committed
Update Readme
1 parent de97d5d commit 2af48ed

6 files changed

Lines changed: 203 additions & 5 deletions

File tree

README.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# Results
2+
3+
Results is a PHP library that provides a set of helper functions and classes for handling optional values and results of operations. It is inspired by the [`Option`](https://doc.rust-lang.org/std/option/enum.Option.html) and [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html) types in Rust.
4+
5+
## Installation
6+
7+
You can install the library via Composer:
8+
9+
```bash
10+
composer require bosunski/results
11+
```
12+
13+
## Usage
14+
15+
### Option
16+
17+
The `Option` type represents an optional value: every `Option` is either `Some` and contains a value, or `None`, and does not.
18+
19+
```php
20+
use function Bosunski\Results\Option;
21+
22+
$some = Option('value'); // Some
23+
$none = Option(null); // None
24+
```
25+
26+
### Result
27+
28+
The `Result` type is a type that represents either success (`Ok`) or failure (`Err`).
29+
30+
```php
31+
use function Bosunski\Results\Result;
32+
33+
$ok = Result('value'); // Ok
34+
$err = Result(new Exception('error')); // Err
35+
```
36+
37+
### Helper Functions
38+
39+
The library provides a set of helper functions for creating `Option` and `Result` instances:
40+
41+
- `Some(mixed $value): Some`
42+
- `None(): None`
43+
- `Option(mixed $value): Option`
44+
- `Ok(mixed $value): Ok`
45+
- `Err(Throwable $e): Err`
46+
- `Result(mixed $value): Ok|Err`
47+
- `wrap(callable $fn): Result`
48+
49+
### Examples
50+
51+
Optional values and results in PHP can be represented using the `Option` and `Result` types provided by the Results library. Here are some examples:
52+
53+
```php
54+
use function Bosunski\Results\Option;
55+
use function Bosunski\Results\Result;
56+
57+
// Options
58+
$some = Option('value'); // Some
59+
$none = Option(null); // None
60+
61+
// Results
62+
$ok = Result('value'); // Ok
63+
$err = Result(new Exception('error')); // Err
64+
```
65+
66+
In the above examples:
67+
68+
- `Option('value')` creates an `Option` that contains a value (referred to as `Some`).
69+
- `Option(null)` creates an `Option` that does not contain a value (referred to as `None`).
70+
- `Result('value')` creates a `Result` that represents a successful operation (`Ok`).
71+
- `Result(new Exception('error'))` creates a `Result` that represents a failed operation (`Err`).
72+
73+
74+
Let's dive into more complex examples of using the `Option` and `Result` types in PHP.
75+
76+
Consider a scenario where we have a function that may or may not return a value. We can use the `Option` type to handle this uncertainty.
77+
78+
```php
79+
use Bosunski\Results\Option as OptionInterface;
80+
use function Bosunski\Results\Option;
81+
82+
function findUserById($id): OptionInterface {
83+
// Assume getUserFromDatabase is a function that returns a User object if found, null otherwise
84+
$user = getUserFromDatabase($id);
85+
86+
return Option($user);
87+
}
88+
89+
$userOption = findUserById(123);
90+
91+
// We can then handle the optional value using the methods provided by the Option type
92+
if ($userOption->isSome()) {
93+
$user = $userOption->unwrap();
94+
// Do something with the user
95+
} else {
96+
// Handle the case where no user was found
97+
}
98+
```
99+
100+
Now, let's consider a scenario where we have a function that can either succeed or fail. We can use the `Result` type to handle this.
101+
102+
```php
103+
use Bosunski\Results\Result\Result as ResultInterface;
104+
use function Bosunski\Results\Result;
105+
106+
function divide(int $numerator, int $denominator): ResultInterface {
107+
if ($denominator == 0) {
108+
return Err(new Exception("Cannot divide by zero"));
109+
} else {
110+
return Ok($numerator / $denominator);
111+
}
112+
}
113+
114+
$result = divide(10, 0);
115+
116+
// We can then handle the result using the methods provided by the Result type
117+
if ($result->isOk()) {
118+
$value = $result->unwrap();
119+
// Do something with the value
120+
} else {
121+
$error = $result->unwrapErr();
122+
// Handle the error
123+
}
124+
```
125+
126+
In these examples, the `Option` and `Result` types provide a way to handle optional values and the results of operations in a safe and expressive manner.
127+
128+
### The wrap Function
129+
130+
The `wrap` function is a utility function provided by the library. It is designed to handle operations that can throw an error. The `wrap` function executes a `callable` and returns its result wrapped in a `Result` object. If the callable function throws an exception, the wrap function catches it and returns an `Err` object containing the exception.
131+
132+
> [!IMPORTANT]
133+
> The error that `wrap` captures depends on your error configuration. Also, `wrap` will only capture instances of `Throwable`. If your function throws something that is not an instance of `Throwable`, it will not be captured by `wrap`.
134+
135+
Here's an example of how you might use the wrap function:
136+
137+
```php
138+
use function Bosunski\Results\wrap;
139+
140+
function mightThrowException(): int {
141+
if (rand(0, 1) === 1) {
142+
throw new Exception('An error occurred');
143+
}
144+
145+
return 42;
146+
}
147+
148+
$result = wrap('mightThrowException');
149+
150+
if ($result->isOk()) {
151+
echo "Success: " . $result->unwrap();
152+
} else {
153+
echo "Error: " . $result->unwrapErr()->getMessage();
154+
}
155+
```
156+
157+
In this example, `mightThrowException` is a function that might throw an exception. We pass this function to `wrap`, which executes it, catch *any* error and wraps the result in a `Result` object. We then check if the result is an instance of `Ok` or `Err` and handle it accordingly.
158+
159+
The `wrap` function provides a safe and expressive way to handle operations that can throw errors, allowing you to focus on your application logic rather than error handling when you don't need to.
160+
161+
162+
## Testing
163+
164+
You can run `composer run test` to run the unit tests for this library.
165+
166+
## License
167+
168+
This project is licensed under the MIT License.

src/Option/None.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,14 @@ public function toResult(Throwable $e): Err
5454
{
5555
return new Err($e);
5656
}
57+
58+
public function isSome(): bool
59+
{
60+
return false;
61+
}
62+
63+
public function isNone(): bool
64+
{
65+
return true;
66+
}
5767
}

src/Option/Option.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,14 @@ public function map(callable $fn): Option;
5151
* @return Result<T, E>
5252
*/
5353
public function toResult(Throwable $e): Result;
54+
55+
/**
56+
* @phpstan-assert-if-true !true $this->isNone()
57+
*/
58+
public function isSome(): bool;
59+
60+
/**
61+
* @phpstan-assert-if-true !true $this->isSome()
62+
*/
63+
public function isNone(): bool;
5464
}

src/Option/Some.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,14 @@ public function toResult(Throwable $e): Ok
6363
{
6464
return new Ok($this->value);
6565
}
66+
67+
public function isSome(): bool
68+
{
69+
return true;
70+
}
71+
72+
public function isNone(): bool
73+
{
74+
return false;
75+
}
6676
}

src/helpers.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ function Result(mixed $value): Ok|Err
7979
}
8080
}
8181

82-
if (! function_exists('wrapResult')) {
82+
if (! function_exists('wrap')) {
8383
/**
8484
* @template T
8585
*
8686
* @param callable(): T $fn
8787
* @return Result<T, Throwable>
8888
*/
89-
function wrapResult(callable $fn): Result
89+
function wrap(callable $fn): Result
9090
{
9191
try {
9292
return Ok($fn());

tests/Unit/HelpersTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use function Results\Option;
1212
use function Results\Result;
1313
use function Results\Some;
14-
use function Results\wrapResult;
14+
use function Results\wrap;
1515

1616
test('Ok returns an Ok', function (): void {
1717
$ok = Ok(1);
@@ -60,14 +60,14 @@
6060
});
6161

6262
test('wrapResult() returns Ok if successful', function (): void {
63-
$ok = wrapResult(fn () => 1);
63+
$ok = wrap(fn () => 1);
6464
expect($ok)->toBeInstanceOf(Ok::class)
6565
->and($ok->unwrap())->toBe(1);
6666
});
6767

6868
test('wrapResult() returns Err if unsuccessful', function (): void {
6969
$exception = new Exception('some message');
70-
$err = wrapResult(fn () => throw $exception);
70+
$err = wrap(fn () => throw $exception);
7171
expect($err)->toBeInstanceOf(Err::class)
7272
->and($e = $err->expectErr(''))->toBeInstanceOf(Exception::class)
7373
->and($e)->toBe($exception)

0 commit comments

Comments
 (0)