mirror of
https://github.com/danog/Valinor.git
synced 2024-12-02 17:48:14 +01:00
1b0ff39af6
It is now mandatory to list all possible class-types that can be inferred by the mapper. This change is a step towards the library being able to deliver powerful new features such as compiling a mapper for better performance. BREAKING CHANGE: the existing calls to `MapperBuilder::infer` that could return several class-names must now add a signature to the callback. The callbacks that require no parameter and always return the same class-name can remain unchanged. For instance: ```php $builder = (new \CuyZ\Valinor\MapperBuilder()) // Can remain unchanged ->infer(SomeInterface::class, fn () => SomeImplementation::class); ``` ```php $builder = (new \CuyZ\Valinor\MapperBuilder()) ->infer( SomeInterface::class, fn (string $type) => match($type) { 'first' => ImplementationA::class, 'second' => ImplementationB::class, default => throw new DomainException("Unhandled `$type`.") } ) // …should be modified with: ->infer( SomeInterface::class, /** @return class-string<ImplementationA|ImplementationB> */ fn (string $type) => match($type) { 'first' => ImplementationA::class, 'second' => ImplementationB::class, default => throw new DomainException("Unhandled `$type`.") } ); ```
57 lines
1.8 KiB
Markdown
57 lines
1.8 KiB
Markdown
# Inferring interfaces
|
|
|
|
When the mapper meets an interface, it needs to understand which implementation
|
|
(a class that implements this interface) will be used — this information must be
|
|
provided in the mapper builder, using the method `infer()`.
|
|
|
|
The callback given to this method must return the name of a class that
|
|
implements the interface. Any arguments can be required by the callback; they
|
|
will be mapped properly using the given source.
|
|
|
|
If the callback can return several class names, it needs to provide a return
|
|
signature with the list of all class-strings that can be returned (see below).
|
|
|
|
```php
|
|
$mapper = (new \CuyZ\Valinor\MapperBuilder())
|
|
->infer(UuidInterface::class, fn () => MyUuid::class)
|
|
->infer(
|
|
SomeInterface::class,
|
|
/** @return class-string<FirstImplementation|SecondImplementation> */
|
|
fn (string $type) => match($type) {
|
|
'first' => FirstImplementation::class,
|
|
'second' => SecondImplementation::class,
|
|
default => throw new DomainException("Unhandled type `$type`.")
|
|
}
|
|
)->mapper();
|
|
|
|
// Will return an instance of `FirstImplementation`
|
|
$mapper->map(SomeInterface::class, [
|
|
'type' => 'first',
|
|
'uuid' => 'a6868d61-acba-406d-bcff-30ecd8c0ceb6',
|
|
'someString' => 'foo',
|
|
]);
|
|
|
|
// Will return an instance of `SecondImplementation`
|
|
$mapper->map(SomeInterface::class, [
|
|
'type' => 'second',
|
|
'uuid' => 'a6868d61-acba-406d-bcff-30ecd8c0ceb6',
|
|
'someInt' => 42,
|
|
]);
|
|
|
|
interface SomeInterface {}
|
|
|
|
final class FirstImplementation implements SomeInterface
|
|
{
|
|
public readonly UuidInterface $uuid;
|
|
|
|
public readonly string $someString;
|
|
}
|
|
|
|
final class SecondImplementation implements SomeInterface
|
|
{
|
|
public readonly UuidInterface $uuid;
|
|
|
|
public readonly int $someInt;
|
|
}
|
|
```
|