makinacorpus / normalization
Tooling for class name to business name maping, some intergration with Symfony and other tools
Installs: 1 267
Dependents: 3
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Requires
- php: >=7.4
Requires (Dev)
- phpunit/phpunit: ^9
- ramsey/uuid: ^3.8 || ^4
- symfony/config: ^5.4 || ^6.0
- symfony/dependency-injection: ^5.4 || ^6.0
- symfony/http-kernel: ^5.4 || ^6.0
- symfony/serializer-pack: ^1.0|^5.0
- symfony/yaml: ^5.4 || ^6.0
This package is not auto-updated.
Last update: 2022-08-08 12:46:29 UTC
README
PHP class name to business domain name naming strategies and normalization helpers.
Main feature is the name map, which provide a reversible and predictible class name to business name and a business name to class name conversion whose goal is to be put in front of any component that exposes PHP class name to the outside world, in order to be able to alias your internal type names to business domain names.
This provides three different class naming strategies:
-
Passthrough name conversion which doesn't convert anything. Exposed names are your PHP class names.
-
Prefix based name conversion which will convert a string such as
Foo\Shop\Domain\Order\Command\BasketProductAdd
toFooShop.Order.Command.BasketProductAdd
considering that theFoo\Shop\Domain
namespace prefix will be always statically converted toFooShop
and replacing separators using.
. -
Static map name conversion which uses a user-provided static map.
-
And of course, you may implement your own strategies using the
MakinaCorpus\Normalization\NameMappingStrategy
interface.
You can configure the name map to hold an infinite number of strategies, each one identified by a tag, which permits to each service using this API to have its own naming strategy.
The name map allows user-defined aliases map, which can hold a infinite number of name aliases for a single PHP class name, allowing your project to be resilient to past conventions. One use case for this is, for example, when you change your naming convention while being plugged over a message bus: your application may continue to consume older messages while being upgraded.
Additionnaly, it provides a few other helpers:
-
A custom
Serializer
interface with a default implementation which uses thesymfony/serializer
component. This allows code using this API to benefit from a replacable serializer. -
A
ramsey/uuid
normalizer and denormalizer forsymfony/serializer
. -
More are likely to be added in the future.
Setup
Install this package:
composer req makinacorpus/normalization
If you are using Symfony, add the bundle in your config/bundles.php
:
<?php return [ // ... Your other bundles. MakinaCorpus\Normalization\Bridge\Symfony\NormalizationBundle::class => ['all' => true], ];
Or you can do a standalone setup of the name map:
use MakinaCorpus\Normalization\NameMap\DefaultNameMap; use MakinaCorpus\Normalization\NameMap\PrefixNameMappingStrategy; $nameMap = new DefaultNameMap( new PrefixNameMappingStrategy( 'MyApp', 'My\\Namespace\\Prefix', ) );
Symfony bundle configuration
Here is an example config/packages/normalization.yaml
file:
# # Sample configuration # normalization: default_strategy: # # Default name mapping strategy configuration. # # Per default the "PrefixNameMappingStrategy" is used, which means # that you need to give an application name prefix string, which will # be all normalized names prefix, and a PHP class namespace prefix # that will identify which PHP classes belongs to you or not. # # Per default the app name is "App" and the namespace prefix is # "App" as well, to mimic default Symfony skeleton app. # app_name: MyApp class_prefix: MyVendor\\MyApp strategy: # # Keys here are arbitrary user-defined tags. # # Tags purpose is to allow API user to define different strategies # for different contextes. # # See \MakinaCorpus\Normalization\NameMap::TAG_* constants which # provides a few samples values. # # Values must be container services identifiers. # command: \App\Infra\Normalization\CustomCommandNameMappingStrategy event: \App\Infra\Normalization\CustomEventNameMappingStrategy static: # # Keys here are arbitrary user-defined tags. # # Tags purpose is to allow API user to define different strategies # for different contextes. # # See \MakinaCorpus\Normalization\NameMap::TAG_* constants which # provides a few samples values. # command: # # Actual business domain name to PHP class name conversion. # map: Php\Native\Type: my_app.normalized_name Php\Other\Native\Type: my_app.other_normalized_name # # Legacy aliases to PHP class name conversion. # aliases: Php\Legacy\Name: Php\Native\Type Php\EvenMoreLegacy\Name: Php\Native\Type my_app.legacy_normalized_name: Php\Native\Type my_app.other_legacy_normalized_name: my_app.normalized_name
Usage
In order to use the name map, simply inject the service into the service needing it:
namespace App\Infra\Bus; use MakinaCorpus\Normalization\NameMap; class SomeBus { public function __construct( private NameMap $nameMap { } /** * This is fictional pseudo-code. */ public function getClassBusinessName(object $message): void { return $this ->nameMap ->fromPhpType( \get_class($message), 'some_tag' ) ; } }
If you are working in a Symfony application, you may simply use the
MakinaCorpus\Normalization\NameMap\NameMapAware
interface on the object
in order for it to be automatically populated by the container:
namespace App\Infra\Bus; use MakinaCorpus\Normalization\NameMap\NameMapAware; use MakinaCorpus\Normalization\NameMap\NameMapAwareTrait; class SomeBus implements NameMapAware { use NameMapAwareTrait; /** * This is fictional pseudo-code. */ public function send(object $message): void { return $this ->getNameMap() ->fromPhpType( \get_class($message), 'some_tag' ) ; } }
Testing
A docker environement with various containers for various PHP versions is
present in the sys/
folder. For tests to work in all PHP versions, you
need to run composer update --prefer-lowest
otherwise PHP 7.4 tests will
fail.
composer install composer update --prefer-lowest cd sys/ ./docker-rebuild.sh # Run this only once ./docker-run.sh