FakerPHP / Faker

Faker is a PHP library that generates fake data for you
https://fakerphp.github.io
Other
3.6k stars 348 forks source link

Missing enum support in Doctrine #897

Closed TomHAnderson closed 2 months ago

TomHAnderson commented 2 months ago

Summary

Doctrine driver does not support enum columns

Versions

Version
PHP 8.3.10
fakerphp/faker 1.23.1

Self-enclosed code snippet for reproduction

        $generator = Factory::create();
        $populator = new Populator($generator, $this->entityManager);
        $populator->addEntity(Media::class, 40);
        $insertedPKs = $populator->execute();

ORM Metadata

<?xml version="1.0"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
  <entity name="App\Doctrine\ORM\Entity\Client\Media" table="ClientMedia">
    <id name="id" type="bigint">
      <generator strategy="AUTO"/>
    </id>
    <field name="provider" type="string" nullable="false" enum-type="App\Doctrine\ORM\Enum\MediaProvider"/>
    <field name="url" type="string" nullable="false"/>
    <field name="createdAt" type="datetime_immutable" nullable="false"/>
    <field name="updatedAt" type="datetime" nullable="false"/>
    <many-to-one field="client" target-entity="App\Doctrine\ORM\Entity\Client\Client" inversed-by="media">
      <join-columns>
        <join-column name="client_id" referenced-column-name="id" nullable="false"/>
      </join-columns>
    </many-to-one>
  </entity>
</doctrine-mapping>

Metadata from the MetdataFactory

    [fieldMappings] => Array
        (
            [provider] => Array
                (
                    [fieldName] => provider
                    [type] => string
                    [nullable] =>
                    [enumType] => App\Doctrine\ORM\Enum\MediaProvider
                    [columnName] => provider
                )

Expected output

null

Actual output

Doctrine\ORM\Mapping\MappingException

  Context: Trying to hydrate enum property "App\Doctrine\ORM\Entity\Client\Media::$provider"
Problem: Case "Voluptate et qui autem consequatur voluptatibus dolorum. Autem alias qui impedit quidem. Perferendis et necessitatibus unde consectetur molestias repellat. Qui occaecati a ab amet consequatur." is not listed in enum "App\Doctrine\ORM\Enum\MediaProvider"
Solution: Either add the case to the enum type or migrate the database column to use another case of the enum

  at vendor/doctrine/orm/src/Mapping/MappingException.php:988
    984▕         string $value,
    985▕         string $enumType,
    986▕         ValueError $previous
    987▕     ): self {
  ➜ 988▕         return new self(sprintf(
    989▕             <<<'EXCEPTION'
    990▕ Context: Trying to hydrate enum property "%s::$%s"
    991▕ Problem: Case "%s" is not listed in enum "%s"
    992▕ Solution: Either add the case to the enum type or migrate the database column to use another case of the enum

      +7 vendor frames

  8   app/Console/Command/Data/Faker.php:83
      Faker\ORM\Doctrine\Populator::execute()
      +12 vendor frames

  21  artisan:35
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

Thoughts

For any enum use the enum object to fetch the random value.

pimjansen commented 2 months ago

We will remove the doctrine support in the future so i dont think there is much interest to add it as well

TomHAnderson commented 2 months ago

I have an interest in it. Removing ORM support is unfortunate: It made quick work of this library.

I've put up a PR that fixes enum in Doctrine fields. There is very little unit testing of the ColumnTypeGuesser so I haven't added that yet. I wanted to show what a fix looks like to see if I can persuade a change to that stance, @pimjansen

TomHAnderson commented 2 months ago

Are you interested in fakerphp/faker-doctrine for 2.0? Here's my latest library; please peruse: https://github.com/API-Skeletons/doctrine-orm-graphql

I can bust out an api-skeletons/faker-doctrine library so I need to know how far you want to distance yourselves from ORM. I think using your namespace would be good but we have dissimilarities in our approach; I use doctrine/coding-standard. I think other ORMs will want integration [back] in 2.0 resulting in more libraries like this proposal.

TomHAnderson commented 2 months ago

I'll just manually assign the enum value with each entity. But the idea for fakerphp/faker-doctrine still stands.

pimjansen commented 2 months ago

Well feel free to create an extention but i dont think we will add all of those in the organisation. There are tons of systems and after a period nothing is maintained so.

If there is a good candidate we will ofc include it in docs and such