Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doctrine 2.14 TypedFieldMapper #213

Open
michnovka opened this issue Dec 20, 2022 · 0 comments
Open

Doctrine 2.14 TypedFieldMapper #213

michnovka opened this issue Dec 20, 2022 · 0 comments

Comments

@michnovka
Copy link
Contributor

michnovka commented Dec 20, 2022

With the introduction of Doctrine 2.14, we can now create our own TypedFieldMapper implementation.

This will allow us to replace

#[ORM\Entity]
class Card
{
    #[ORM\Column(Suit::class)]
    protected Suit $suit;
}

with

#[ORM\Entity]
class Card
{
    #[ORM\Column]
    protected Suit $suit;
}

I propose we create our own that will check if the enum is specified in types list

elao_enum:
  doctrine:
    types:
      App\Enum\Suit: ~ # Defaults to `{ class: App\Enum\Suit, default: null, type: single }`
      permissions: { class: App\Enum\Permission } # You can set a name different from the enum FQCN
      permissions_bag: { class: App\Enum\Permissions, type: flagbag } # values are stored as an int and retrieved as FlagBag object
      App\Enum\RequestStatus: { default: 200 } # Default value from enum cases, in case the db value is NULL
    prepend_typed_field_mapper: true #default false

If elao_enum.doctrine.types.prepend_typed_field_mapper is set to true (maybe we can make this a default?) then I would inject our typed field mapper into doctrine config. The way to do this would be:

/** @var Doctrine\ORM\Configuration $configuration */
$currentTypedFieldMapper = $configuration->getTypedFieldMapper();
$newTypedFieldMapper = new Doctrine\ORM\Mapping\ChainTypedFieldMapper(
    new ElaoTypedFieldMapper(),
    $currentTypedFieldMapper
);
$configuration->setTypedFieldMapper($newTypedFieldMapper);

This will ensure that the already used typed field mapper is kept, and ElaoTypedFieldMapper will only take care of the elao enum types.

The actual typed field mapper is simple, can look sth like this:

<?php
final class ElaoTypedFieldMapper implements TypedFieldMapper
{
    /**
     * {@inheritdoc}
     */
    public function validateAndComplete(array $mapping, ReflectionProperty $field): array
    {
        $type = $field->getType();

        if (
            ! isset($mapping['type'])
            && ($type instanceof ReflectionNamedType)
        ) {
            $implementsReadableEnumInterface = // find out using reflection or is_subclass_of
            if (! $type->isBuiltin() && enum_exists($type->getName()) && $implementsReadableEnumInterface) {
                $mapping['type'] = 'the correctly derived enum DBAL type class name';
            }
        }

        return $mapping;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant