11# Welcome to PhpBox
22
3- PhpBox contains exactly one class: ` Box ` .
4-
5- You can find it here: [ src/Box .php] ( src/Box .php )
3+ PhpBox contains two classes:
4+ - ` Box ` [ src/Box.php ] ( src/Box.php )
5+ - ` TryBox ` [ src/TryBox .php] ( src/TryBox .php )
66
77# Installation
8- Currently, there is no composer package.
9-
10- Simply copy the ` Box.php ` file to your project and adjust its namespace if needed.
8+ A composer package is in the works, but I recommend just copying the files into your project for now.
119
1210# Requirements
1311The only hard requirement is PHP 8.0 or higher.
@@ -23,25 +21,20 @@ You put any value into a box.
2321
2422Then you can chain map(), dump() and assert() calls on it.
2523
26- To get the value out of the box, call unbox () or get().
24+ To get the value out of the box, call value () or get().
2725
28- ## Note
29- In an earlier version:
30- - map() was called pipe()
31- - get() was called pull()
32-
33- ## Examples
26+ ## Box Examples
3427
3528``` php
3629$value = Box::of(5)
3730 ->map(fn($value) => $value + 1)
3831 ->map(fn($value) => $value * 2)
39- ->unbox ();
32+ ->value ();
4033
4134echo $value; // 12
4235```
4336
44- Use get() to combine map() and unbox () in one call:
37+ Use get() to combine map() and value () in one call:
4538``` php
4639$value = Box::of(5)
4740 ->map(fn($value) => $value + 1)
@@ -57,7 +50,7 @@ $isEven = fn($value) => $value % 2 === 0;
5750$value = Box::of(5)
5851 ->map(fn($it) => $it + 1)->assert(6)
5952 ->map(fn($it) => $it * 2)->assert($isEven)->dump()
60- ->unbox ();
53+ ->value ();
6154
6255echo $value; // 12
6356```
@@ -96,14 +89,74 @@ function assertEmail(Box $box): Box
9689 ->assert(fn(string $x) => filter_var($x, FILTER_VALIDATE_EMAIL), 'Not an email');
9790}
9891
99- $validEmail = Box::of('')->flatMap(assertEmail(...))->unbox ();
92+ $validEmail = Box::of('')->flatMap(assertEmail(...))->value ();
10093// throws LogicException: "Too short"
10194
10295$user = Box::of('john@example.org')
10396 ->mod(fn($box) => assertEmail($box))
10497 ->get(fn($email) => $userRepository->create(['email' => $email]));
10598```
10699
100+ ## TryBox Examples
101+
102+ TryBox works just like Box, except that it catches any and all errors instead of blowing up directly.
103+ Its value() method has a more complicated return type, which is either T or Throwable.
104+ - advantage: you can run a chain without risk of blowing up (subsequent map() calls will be skipped),
105+ and then decide what to do with the error at the end.
106+ - disadvantage: you have to handle the error case even if you're sure it will never happen.
107+
108+ Let's define a realistic function that sometimes throws an error (like a database call or an API request). In this
109+ case it either returns whatever was passed in or throws a RuntimeException at random.
110+ ``` php
111+ /**
112+ * @template T
113+ * @param T $value
114+ * @return T
115+ *
116+ * @throws RuntimeException
117+ */
118+ function roulette($value)
119+ {
120+ if (random_int(0, 1) === 1) {
121+ throw new RuntimeException('boo');
122+ }
123+
124+ return $value;
125+ }
126+ ```
127+
128+ Let's use this dangerous function in a TryBox chain:
129+ ``` php
130+ $result = TryBox::of(5)
131+ ->map(fn($value) => roulette($value)) // TryBox stores the exception
132+ ->map(fn($value) => $value * 2)
133+ ->map(fn($value) => $value + 1)
134+ ->value();
135+
136+ // type signature is int|Throwable, so we have to handle the error case
137+ if ($result instanceof Throwable) {
138+ echo $result->getMessage(); // boo
139+ return;
140+ }
141+
142+ // if we reach this line, $result is guaranteed to be an int
143+ $calc = $result + 1;
144+ echo $calc;
145+ ```
146+
147+ If you are sure the error case will never happen, or simply don't care, you can use rip() instead of value():
148+ ` rip() ` will either throw the stored error (if any) or return the value of type T.
149+ ``` php
150+ $result = TryBox::of(5)
151+ ->map(fn($value) => roulette($value))
152+ ->map(fn($value) => $value * 2)
153+ ->map(fn($value) => $value + 1)
154+ ->rip(); // The original runtime exception will be thrown here, if present
155+
156+ // if we reach this line, $result is guaranteed to be an int
157+ $calc = $result + 1;
158+ ```
159+
107160# Type Safety
108161Thanks to meticulously crafted PHPDoc annotations, this class is type safe if you use PHPStan for static analysis.
109162
0 commit comments