Notable changes
This release brings a set of new features to the library:
- Normalizer configurators support
- Shaped list type support
key-oftype support- and more!
Enjoy! 🎉
Normalizer configurators support
A set of configurators is now available for the normalizer, mirroring the mapper configurators introduced in the previous release. Each one can be used either globally through the configureWith() method or locally as an attribute targeting a specific class or property.
Keys case normalization
Four configurators normalize the keys of a normalized object to a given case. This is useful to expose data following a naming convention that differs from the one used in the PHP codebase.
| Configurator | Example |
|---|---|
new NormalizeKeysToCamelCase()
| first_name → firstName
|
new NormalizeKeysToPascalCase()
| first_name → FirstName
|
new NormalizeKeysToSnakeCase()
| firstName → first_name
|
new NormalizeKeysToKebabCase()
| firstName → first-name
|
Used globally, the keys of every normalized object are converted:
use CuyZ\Valinor\Normalizer\Configurator\NormalizeKeysToSnakeCase;
use CuyZ\Valinor\Normalizer\Format;
use CuyZ\Valinor\NormalizerBuilder;
$userAsArray = (new NormalizerBuilder())
->configureWith(new NormalizeKeysToSnakeCase())
->normalizer(Format::array())
->normalize($user);
// ['first_name' => 'John']Used as an attribute, only the keys of the targeted class are converted:
use CuyZ\Valinor\Normalizer\Configurator\NormalizeKeysToSnakeCase;
#[NormalizeKeysToSnakeCase]
final readonly class User
{
public function __construct(
public string $firstName,
) {}
}
// ['first_name' => 'John']Date and time normalization
The NormalizeDateTimeFormat configurator normalizes any DateTimeInterface instance to a string using the given format.
Used globally, every date and time encountered during normalization is formatted:
use CuyZ\Valinor\Normalizer\Configurator\NormalizeDateTimeFormat;
use CuyZ\Valinor\Normalizer\Format;
use CuyZ\Valinor\NormalizerBuilder;
$userAsArray = (new NormalizerBuilder())
->configureWith(new NormalizeDateTimeFormat(DATE_ATOM))
->normalizer(Format::array())
->normalize($user);
// [
// 'name' => 'Jane Doe',
// 'createdAt' => '2000-01-01T00:00:00+00:00',
// ]Used as an attribute, only the targeted property is formatted:
use CuyZ\Valinor\Normalizer\Configurator\NormalizeDateTimeFormat;
final readonly class User
{
public function __construct(
public string $name,
#[NormalizeDateTimeFormat(DATE_ATOM)]
public DateTimeInterface $createdAt,
) {}
}Shaped list type support
The shaped list type list{…} is now supported. It works like a shaped array but enforces sequential integer keys starting at 0, making it the right type to describe a tuple-like list of values.
final readonly class SomeClass
{
public function __construct(
/** @var list{string, int, float} */
public array $shapedList,
/** @var list{0: string, 1: int} */
public array $shapedListWithExplicitKeys,
/** @var list{0: string, 1?: int} */
public array $shapedListWithOptionalElement,
/** @var list{string, int, ...} */
public array $unsealedShapedList,
/** @var list{string, int, ...list<float>} */
public array $unsealedShapedListWithExplicitType,
/** @var list{string, ...<float>} */
public array $unsealedShapedListWithShorthandType,
) {}
}key-of type support
The key-of<T> type is now supported. It extracts the key types from enums, arrays, lists, and shaped arrays, including array constants. It is compatible with the same syntax as accepted by PHPStan and Psalm.
enum SomeBackedEnum: string
{
case FOO = 'foo';
case BAR = 'bar';
}
final readonly class SomeClassWithConstants
{
public const SOME_ARRAY = ['foo' => 1, 'bar' => 2];
}
final readonly class SomeClass
{
public function __construct(
// Accepts 'FOO' or 'BAR' (the case names of the enum)
/** @var key-of<SomeBackedEnum> */
public string $enumKey,
// Accepts 'foo' or 'bar' (the keys of the shaped array)
/** @var key-of<array{foo: string, bar: int}> */
public string $shapedArrayKey,
// Accepts the key type of the array (string here)
/** @var key-of<array<string, int>> */
public string $arrayKey,
// Accepts 'foo' or 'bar' (the keys of the class constant array)
/** @var key-of<SomeClassWithConstants::SOME_ARRAY> */
public string $constantArrayKey,
) {}
}Features
- Add normalizer configurator
ConvertDateTime(bf688b) - Add normalizer configurator
NormalizeKeysToCamelCase(b0d38f) - Add normalizer configurator
NormalizeKeysToKebabCase(9826ca) - Add normalizer configurator
NormalizeKeysToPascalCase(53bff2) - Add normalizer configurator
NormalizeKeysToSnakeCase(c831e0) - Add support for
key-oftype mapping (ff16b2) - Add support for covariant templates (c31f24)
- Add support for shaped list type (eeeb5c)
- Support local alias types referencing other local aliases (757256)
- Support null values for class constants (5cd356)
- Support parenthesized union types (21a04b)
Bug Fixes
- Prevent memory leak with functions' reflection (6d36a0)
- Rank union candidates by matching arguments (126cf7)
Internal
- Add security vulnerability reporting guidelines (b80e2a)
- Memoize parent class definitions (17d8cf)
- Move int to float casting outside
Shell(f84e78)