-
-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #95 from kynx/backed-enum-strategy
Add BackedEnumStrategy
- Loading branch information
Showing
8 changed files
with
339 additions
and
9 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# BackedEnum | ||
|
||
INFO: **New Feature** | ||
Available since version 4.8.0 | ||
|
||
MISSING: **Installation Requirements** | ||
[Enumerations](https://www.php.net/manual/language.enumerations.overview.php) require PHP version 8.1 or higher. | ||
|
||
The `BackedEnumStrategy` provides **bidirectional conversion between strings | ||
or integers and [Backed Enums](https://www.php.net/manual/en/language.enumerations.backed.php)**. | ||
|
||
The code examples below will use the following backed enum, representing a | ||
genre of music: | ||
|
||
```php | ||
enum Genre: string | ||
{ | ||
case Pop = 'pop'; | ||
case Blues = 'blues'; | ||
case Jazz = 'jazz'; | ||
} | ||
``` | ||
|
||
## Basic Usage | ||
|
||
The following code example shows standalone usage without adding the strategy | ||
to a hydrator. | ||
|
||
### Create and Configure Strategy | ||
|
||
Create the strategy passing the class name of the enum it will hydrate and extract: | ||
|
||
```php | ||
$strategy = new Laminas\Hydrator\Strategy\BackedEnumStrategy(Genre::class); | ||
``` | ||
|
||
### Hydrate Data | ||
|
||
```php | ||
$hydrated = $strategy->hydrate('blues', null); | ||
var_dump($hydrated); // enum Genre::Blues : string("blues"); | ||
``` | ||
|
||
### Extract Data | ||
|
||
```php | ||
$extracted = $strategy->extract(Genre::Pop); | ||
var_dump($extracted); // string(3) "pop" | ||
``` | ||
|
||
## Example | ||
|
||
The following example demonstrates hydration for a class with a property. | ||
|
||
An example class which represents an album with a music genre: | ||
|
||
```php | ||
class Album | ||
{ | ||
private ?Genre $genre; | ||
|
||
public function __construct(?Genre $genre = null) | ||
{ | ||
$this->genre = $genre; | ||
} | ||
|
||
public function getGenre() : Genre | ||
{ | ||
return $this->genre; | ||
} | ||
} | ||
``` | ||
|
||
### Create Hydrator and Add Atrategy | ||
|
||
Create a hydrator and add the `BackedEnumStrategy` as a strategy: | ||
|
||
```php | ||
$hydrator = new Laminas\Hydrator\ReflectionHydrator(); | ||
$hydrator->addStrategy( | ||
'genre', | ||
new Laminas\Hydrator\Strategy\BackedEnumStrategy(Genre::class) | ||
); | ||
``` | ||
|
||
### Hydrate Data | ||
|
||
Create an instance of the example class and hydrate data: | ||
|
||
```php | ||
$album = new Album(); | ||
$hydrator->hydrate(['genre' => 'jazz'], $album); | ||
|
||
echo $album->getGenre()->value; // "jazz" | ||
``` | ||
|
||
### Extract Data | ||
|
||
```php | ||
$extracted = $hydrator->extract($album); | ||
|
||
echo $extracted['genre']; // "jazz" | ||
``` |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Laminas\Hydrator\Strategy; | ||
|
||
use BackedEnum; | ||
use Laminas\Hydrator\Strategy\Exception\InvalidArgumentException; | ||
use ValueError; | ||
|
||
use function get_debug_type; | ||
use function is_int; | ||
use function is_string; | ||
use function sprintf; | ||
|
||
/** | ||
* @template T of BackedEnum | ||
*/ | ||
final class BackedEnumStrategy implements StrategyInterface | ||
{ | ||
/** @var class-string<T> */ | ||
private string $enumClass; | ||
|
||
/** | ||
* @param class-string<T> $enumClass | ||
*/ | ||
public function __construct(string $enumClass) | ||
{ | ||
$this->enumClass = $enumClass; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public function extract($value, ?object $object = null) | ||
{ | ||
if (! $value instanceof $this->enumClass) { | ||
throw new InvalidArgumentException(sprintf( | ||
"Value must be a %s; %s provided", | ||
$this->enumClass, | ||
get_debug_type($value) | ||
)); | ||
} | ||
|
||
return $value->value; | ||
} | ||
|
||
/** | ||
* @param mixed $value | ||
* @return T | ||
*/ | ||
public function hydrate($value, ?array $data) | ||
{ | ||
if ($value instanceof $this->enumClass) { | ||
return $value; | ||
} | ||
|
||
if (! (is_int($value) || is_string($value))) { | ||
throw new InvalidArgumentException(sprintf( | ||
"Value must be string or int; %s provided", | ||
get_debug_type($value) | ||
)); | ||
} | ||
|
||
try { | ||
return $this->enumClass::from($value); | ||
} catch (ValueError $error) { | ||
throw new InvalidArgumentException(sprintf( | ||
"Value '%s' is not a valid scalar value for %s", | ||
(string) $value, | ||
$this->enumClass | ||
), 0, $error); | ||
} | ||
} | ||
} |
Oops, something went wrong.