digital-craftsman / self-aware-normalizers
Adds interfaces and normalizers that allow value objects to normalize and denormalize themselves.
Installs: 78
Dependents: 4
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: 8.3.*|8.4.*
- doctrine/dbal: ^3.3.6
- symfony/framework-bundle: ^7.1
- symfony/serializer: ^7.1
Requires (Dev)
- digital-craftsman/ids: ^1.3
- friendsofphp/php-cs-fixer: ^v3.59.3
- infection/infection: 0.27.*
- phpunit/phpunit: ^10.5
- symfony/property-access: ^7.1
- symfony/property-info: ^7.1
- vimeo/psalm: ^5.25
This package is auto-updated.
Last update: 2024-12-05 12:13:36 UTC
README
A Symfony bundle to enable value objects and DTOs to normalize and denormalize themselves through implementing simple interfaces that normalize to scalar values and denormalize themselves from scalar values (string
, int
, float
, bool
and array
). Adding this kind of logic to the classes themselves might be considered a bad practice, but depending on the use case it will actually be better due to the fact that the data structure and the normalization need to be changed together.
The name implies that the value objects and DTOs are self-aware in the sense that they know how to normalize and denormalize themselves and that they are self-aware enough to do so 🙂
As it's a central part of an application, it's tested thoroughly (including mutation testing).
Installation and configuration
Install package through composer:
composer require digital-craftsman/self-aware-normalizers
⚠️ This bundle can be used (and is being used) in production, but hasn't reached version 1.0 yet. Therefore, there will be breaking changes between minor versions. I'd recommend that you require the bundle only with the current minor version like
composer require digital-craftsman/self-aware-normalizers:0.2.*
. Breaking changes are described in the releases and the changelog. Updates are described in the upgrade guide.
Usage
Normalizers
To make the normalization process easier, there are the following normalizers included:
StringNormalizableNormalizer
IntNormalizableNormalizer
FloatNormalizableNormalizer
BoolNormalizableNormalizer
ArrayNormalizableNormalizer
Additionally, there is an interface for each of the normalizers. Every class that implements one of the interfaces, will be automatically normalized to the respected type. This means putting the logic of how serialization of a class works within the class. That's not really seen as a good practice. In my experience, the data structure and the normalization need to be changed together. So, I like it better to have both in one place. I've used this approach in multiple large scale projects for years and haven't had a single issue with it yet. But your mileage may vary.
Doctrine types
When using the normalizers, you can also use the same logic for doctrine types. Simply create a new doctrine type extending of one of the following types and register them:
StringNormalizableType
StringEnumType
IntNormalizableType
FloatNormalizableType
BoolNormalizableType
ArrayNormalizableType
As an added bonus, this makes sure, that the structure is always the same no matter if you're using Doctrine to read from the data or a normalizer.