@@ -84,24 +84,28 @@ $user = Box::of($inputEmail)
8484 ->get(fn($it) => $userRepository->create(['email' => $it]));
8585```
8686
87- Or make it shorter by using higher abstraction levels:
88-
87+ Using flatMap, you can compose presets of operations on boxes:
8988``` php
90- // potentially defined elsewhere
91- function isValidEmail(mixed $email ): bool
89+ /** @throws LogicException */
90+ function assertEmail(Box $box ): Box
9291{
93- return is_string($email)
94- && strlen($email) > 0
95- && strlen($email) < 256
96- && filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
92+ return $box
93+ ->assert(fn($x) => is_string($x), 'Not a string')
94+ ->assert(fn(string $x) => strlen($x) > 0, 'Too short')
95+ ->assert(fn(string $x) => strlen($x) < 256, 'Too long')
96+ ->assert(fn(string $x) => filter_var($x, FILTER_VALIDATE_EMAIL), 'Not an email');
9797}
9898
99- $validEmail = Box::of('john.doe@example.org ')->assertGet(isValidEmail (...));
100- // $validEmail === 'john.doe@example.org'
99+ $validEmail = Box::of('')->flatMap(assertEmail (...))->unbox( );
100+ // throws LogicException: "Value is too short"
101101
102- $validEmail2 = Box::of('asdf')->assertGet(isValidEmail(...));
103- // throws LogicException
102+ $user = Box::of('john@example.org')
103+ ->flatMap(fn($box) => assertEmail($box))
104+ ->get(fn($email) => $userRepository->create(['email' => $email]));
104105```
106+ Note, in this example we still have 4 separate assertions and error messages.
107+ Using flatMap is the key here. Unlike map(), which transforms the value inside the Box,
108+ flatMap() transforms the Box itself. This allows us to compose behavior in a more functional way.
105109
106110# Type Safety
107111Thanks to meticulously crafted PHPDoc annotations, this class is type safe if you use PHPStan for static analysis.
0 commit comments