-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add TypedFieldMapper for automatic mapping of typed PHP fields to DBA…
…L types Previously, only a predefined set of automatic mappings was allowed, such as int, float, boolean, DateTime etc. With this extension, it is possible to supply custom TypedFieldMapper implementation which takes as parameter the ReflectionProperty of a given field and decides the appropriate mapping. A new configuration option was added to set and get the TypedFieldMapper. The old logic was moved into a class DefaultTypedFieldMapper which is used by default when no mapper is supplied. The selected TypedFieldMapper is passed into ClassMetadataInfo constructor. If empty, the DefaultTypedFieldMapper is used. There is also ChainTypedFieldMapper class which allows chaining multiple TypedFieldMappers and apply them in a cascade (always if a field gets type assigned by the earlier mapper in the list, it will not be changed later).
- Loading branch information
Showing
17 changed files
with
564 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Doctrine\ORM\Mapping; | ||
|
||
final class ChainTypedFieldMapper implements TypedFieldMapper | ||
{ | ||
/** | ||
* @readonly | ||
* @var TypedFieldMapper[] $typedFieldMappers | ||
*/ | ||
private array $typedFieldMappers; | ||
|
||
public function __construct(TypedFieldMapper ...$typedFieldMappers) | ||
{ | ||
$this->typedFieldMappers = $typedFieldMappers; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validateAndCompleteTypedFieldMapping($mapping, $field): array | ||
{ | ||
foreach ($this->typedFieldMappers as $typedFieldMapper) { | ||
$mapping = $typedFieldMapper->validateAndCompleteTypedFieldMapping($mapping, $field); | ||
} | ||
|
||
return $mapping; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Doctrine\ORM\Mapping; | ||
|
||
use DateInterval; | ||
use DateTime; | ||
use DateTimeImmutable; | ||
use Doctrine\DBAL\Types\Type; | ||
use Doctrine\DBAL\Types\Types; | ||
use ReflectionEnum; | ||
use ReflectionNamedType; | ||
|
||
use function array_merge; | ||
use function assert; | ||
use function enum_exists; | ||
|
||
use const PHP_VERSION_ID; | ||
|
||
/** @psalm-import-type ScalarName from ClassMetadataInfo */ | ||
final class DefaultTypedFieldMapper implements TypedFieldMapper | ||
{ | ||
/** @var array<class-string|ScalarName, class-string<Type>|string> $typedFieldMappings */ | ||
protected $typedFieldMappings; | ||
|
||
/** @param array<class-string|ScalarName, class-string<Type>|string> $typedFieldMappings */ | ||
public function __construct($typedFieldMappings = []) | ||
{ | ||
$this->typedFieldMappings = $typedFieldMappings; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validateAndCompleteTypedFieldMapping($mapping, $field): array | ||
{ | ||
$type = $field->getType(); | ||
|
||
if ( | ||
! isset($mapping['type']) | ||
&& ($type instanceof ReflectionNamedType) | ||
) { | ||
if (PHP_VERSION_ID >= 80100 && ! $type->isBuiltin() && enum_exists($type->getName())) { | ||
$mapping['enumType'] = $type->getName(); | ||
|
||
$reflection = new ReflectionEnum($type->getName()); | ||
$type = $reflection->getBackingType(); | ||
|
||
assert($type instanceof ReflectionNamedType); | ||
} | ||
|
||
$defaultTypedFieldMappings = [ | ||
DateInterval::class => Types::DATEINTERVAL, | ||
DateTime::class => Types::DATETIME_MUTABLE, | ||
DateTimeImmutable::class => Types::DATETIME_IMMUTABLE, | ||
'array' => Types::JSON, | ||
'bool' => Types::BOOLEAN, | ||
'float' => Types::FLOAT, | ||
'int' => Types::INTEGER, | ||
'string' => Types::STRING, | ||
]; | ||
|
||
$typedFieldMappings = array_merge($defaultTypedFieldMappings, $this->typedFieldMappings); | ||
|
||
if (isset($typedFieldMappings[$type->getName()])) { | ||
$mapping['type'] = $typedFieldMappings[$type->getName()]; | ||
} | ||
} | ||
|
||
return $mapping; | ||
} | ||
} |
Oops, something went wrong.