|
4 | 4 | [](https://packagist.org/packages/bluepsyduck/mapper-manager)
|
5 | 5 | [](https://travis-ci.com/BluePsyduck/mapper-manager)
|
6 | 6 | [](https://codecov.io/gh/BluePsyduck/mapper-manager)
|
| 7 | + |
| 8 | +The Mapper Manager is, as the name already suggests, a manager of mappers between different types of objects. |
| 9 | + |
| 10 | +## Mapper |
| 11 | + |
| 12 | +The mapper supports different types of mappers, which have the difference in how they evaluate whether they can map |
| 13 | +a certain pair of objects or not. Each type of mapper comes with an interface and a corresponding adapter for the |
| 14 | +manager to handle this type of mappers. New types can always be added in the client code if there is a need for them. |
| 15 | + |
| 16 | +### Static Mapper |
| 17 | + |
| 18 | +A static mapper implementing the `StaticMapperInterface` knows the combination of source and destination object it |
| 19 | +supports based only on the classes, without knowing the actual instances of the objects. The support is evaluated once |
| 20 | +when the mapper is added to the manager. |
| 21 | + |
| 22 | +Note: The classes of source and destination must match exactly, the static mapper does not check for any inheritance. |
| 23 | +For example, if there is a class `A` and a class `B extends A`, and the mapper returns `A` as supported class, it won't |
| 24 | +match if an instance of `B` is passed instead. If inheritance must be supported, use a dynamic mapper instead. |
| 25 | + |
| 26 | +It is recommended to always use static mappers if possible, as matching the mapper in the manager is faster with |
| 27 | +static mappers than with dynamic ones. |
| 28 | + |
| 29 | +#### Example |
| 30 | + |
| 31 | +```php |
| 32 | +<?php |
| 33 | + |
| 34 | +use BluePsyduck\MapperManager\Mapper\StaticMapperInterface; |
| 35 | + |
| 36 | +class ExampleStaticMapper implements StaticMapperInterface |
| 37 | +{ |
| 38 | + /** |
| 39 | + * Returns the source class supported by this mapper. |
| 40 | + * @return string |
| 41 | + */ |
| 42 | + public function getSupportedSourceClass(): string |
| 43 | + { |
| 44 | + return DatabaseItem::class; |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Returns the destination class supported by this mapper. |
| 49 | + * @return string |
| 50 | + */ |
| 51 | + public function getSupportedDestinationClass(): string |
| 52 | + { |
| 53 | + return ResponseItem::class; |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Maps the source object to the destination one. |
| 58 | + * @param DatabaseItem $source |
| 59 | + * @param ResponseItem $destination |
| 60 | + */ |
| 61 | + public function map($source, $destination): void |
| 62 | + { |
| 63 | + $destination->setName($source->getName()) |
| 64 | + ->setDescription($source->getDescription()); |
| 65 | + } |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +### Dynamic Mapper |
| 70 | + |
| 71 | +A dynamic mapper implementing the `DynamicMapperInterface` will decide whether a combination of source and destination |
| 72 | +object is supported on the actual instances of the objects. This allows to add additional criteria for support based |
| 73 | +on the two involved objects. The support is re-evaluated for each source and destination object passed to the mapper |
| 74 | +manager. |
| 75 | + |
| 76 | +#### Example |
| 77 | + |
| 78 | +```php |
| 79 | +<?php |
| 80 | + |
| 81 | +use BluePsyduck\MapperManager\Mapper\DynamicMapperInterface; |
| 82 | + |
| 83 | +class ExampleDynamicMapper implements DynamicMapperInterface |
| 84 | +{ |
| 85 | + /** |
| 86 | + * Returns whether the mapper supports the combination of source and destination object. |
| 87 | + * @param object $source |
| 88 | + * @param object $destination |
| 89 | + * @return bool |
| 90 | + */ |
| 91 | + public function supports($source, $destination): bool |
| 92 | + { |
| 93 | + return $source instanceof DatabaseItem::class |
| 94 | + && $destination instanceof ResponseItem::class |
| 95 | + && $source->getType() === 'public'; // Additional condition not possible with a static mapper. |
| 96 | + } |
| 97 | + |
| 98 | + /** |
| 99 | + * Maps the source object to the destination one. |
| 100 | + * @param DatabaseItem $source |
| 101 | + * @param ResponseItem $destination |
| 102 | + */ |
| 103 | + public function map($source, $destination): void |
| 104 | + { |
| 105 | + $destination->setName($source->getName()) |
| 106 | + ->setDescription($source->getDescription()); |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +## Usage |
| 112 | + |
| 113 | +The usage of the mapper manager is rather straight forward: Create an instance of the `MapperManager` class, add some |
| 114 | +adapters, and afterwards add your actual mapper implementations. |
| 115 | + |
| 116 | +```php |
| 117 | +<?php |
| 118 | + |
| 119 | +use BluePsyduck\MapperManager\MapperManager; |
| 120 | +use BluePsyduck\MapperManager\Adapter\DynamicMapperAdapter; |
| 121 | +use BluePsyduck\MapperManager\Adapter\StaticMapperAdapter; |
| 122 | + |
| 123 | +$mapperManager = new MapperManager(); |
| 124 | + |
| 125 | +// Add the default adapters included in the library. |
| 126 | +$mapperManager->addAdapter(new StaticMapperAdapter()); |
| 127 | +$mapperManager->addAdapter(new DynamicMapperAdapter()); |
| 128 | + |
| 129 | +// Add your actual mappers. |
| 130 | +$mapperManager->addMapper(new ExampleStaticMapper()); |
| 131 | +$mapperManager->addMapper(new ExampleDynamicMapper()); |
| 132 | + |
| 133 | +// Actually map objects. |
| 134 | +$mapperManager->map($databaseItem, $responseItem); |
| 135 | +``` |
| 136 | + |
| 137 | +### Zend Expressive |
| 138 | + |
| 139 | +When using Zend Expressive, you can add the `ConfigProvider` of the library to your application config and access |
| 140 | +the already-initialized mapper manager through the container using `MapperManagerInterface::class` or |
| 141 | +`MapperManager::class` as alias. |
| 142 | + |
| 143 | +Add the following config to your project to customize the manager: |
| 144 | + |
| 145 | +```php |
| 146 | +<?php |
| 147 | + |
| 148 | +use BluePsyduck\MapperManager\Constant\ConfigKey; |
| 149 | + |
| 150 | +[ |
| 151 | + ConfigKey::MAIN => [ |
| 152 | + ConfigKey::ADAPTERS => [ |
| 153 | + // The aliases of the adapters to add to the manager. |
| 154 | + // The adapters must be accessible through the container with these aliases. |
| 155 | + // The StaticMapperAdapter and DynamicMapperAdapter are added automatically. |
| 156 | + ], |
| 157 | + ConfigKey::MAPPERS => [ |
| 158 | + // The aliases of the mappers to add to the container. |
| 159 | + // The mappers must be accessible through the container with these aliases. |
| 160 | + ], |
| 161 | + ], |
| 162 | +]; |
| 163 | +``` |
| 164 | + |
| 165 | +Then access the mapper manager through the container: |
| 166 | + |
| 167 | +```php |
| 168 | +<?php |
| 169 | + |
| 170 | +use BluePsyduck\MapperManager\MapperManagerInterface; |
| 171 | + |
| 172 | +// Fetch the mapper manager from the container. |
| 173 | +$mapperManager = $container->get(MapperManagerInterface::class); |
| 174 | + |
| 175 | +// Actually map objects. |
| 176 | +$mapperManager->map($databaseItem, $responseItem); |
| 177 | +``` |
0 commit comments