8000 [UId/Doctrine] Entity repository error "ConversionException" · Issue #38929 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[UId/Doctrine] Entity repository error "ConversionException" #38929

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

Closed
94noni opened this issue Oct 31, 2020 · 7 comments · Fixed by #38986
Closed

[UId/Doctrine] Entity repository error "ConversionException" #38929

94noni opened this issue Oct 31, 2020 · 7 comments · Fixed by #38986

Comments

@94noni
Copy link
Contributor
94noni commented Oct 31, 2020

Symfony version(s) affected: 5.2.0-beta3

Description

Entity repository failed to retrieve an entity with an Uid property with method findOneBy

Doctrine\DBAL\Types\ConversionException:
Could not convert PHP value 'e2e64173-174b-4109-a3ce-971a1e9d3b56' of type 'string' to type 'uuid'.
Expected one of the following types: null, Symfony\Component\Uid\AbstractUid

How to reproduce

See code after

Possible Solution

If I replace the doctrine findOneByUuid with a personal repo method findMyHumidorWithUuid it works.

Additional context

I am using Messenger and pass the object uuid to the async logic, then inside the handler I am trying to retrieve the original object, and the error occurs.

Some code:

use Symfony\Component\Uid\Uuid;
[...]
/**
 * @ORM\Entity(repositoryClass="App\Repository\HumidorRepository")
 */
class Humidor
{
[...]
    /**
     * @ORM\Column(type="uuid", unique=true)
     */
    private $uuid;
[...]
    public function __construct()
    {
        $this->uuid = Uuid::v4();
[...]
    }
}

Failure code:

// in code
// $uuid is 'e2e64173-174b-4109-a3ce-971a1e9d3b56'
$humidor = $humidorRepository->findOneByUuid($uuid);
See stack trace (inside a controller reproducer)
Doctrine\DBAL\Types\ConversionException:
Could not convert PHP value 'e2e64173-174b-4109-a3ce-971a1e9d3b56' of type 'string' to type 'uuid'. Expected one of the following types: null, Symfony\Component\Uid\AbstractUid

  at vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php:79
  at Doctrine\DBAL\Types\ConversionException::conversionFailedInvalidType('e2e64173-174b-4109-a3ce-971a1e9d3b56', 'uuid', array('null', 'Symfony\\Component\\Uid\\AbstractUid'))
     (vendor/symfony/doctrine-bridge/Types/AbstractUidType.php:68)
  at Symfony\Bridge\Doctrine\Types\AbstractUidType->convertToDatabaseValue('e2e64173-174b-4109-a3ce-971a1e9d3b56', object(MySQL57Platform))
     (vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1997)
  at Doctrine\DBAL\Connection->getBindingInfo('e2e64173-174b-4109-a3ce-971a1e9d3b56', object(UuidType))
     (vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:2030)
  at Doctrine\DBAL\Connection->resolveParams(array('e2e64173-174b-4109-a3ce-971a1e9d3b56'), array('uuid'))
     (vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:2121)
  at Doctrine\DBAL\Connection->handleExceptionDuringQuery(object(ConversionException), 'SELECT t0.id AS id_1, t0.uuid AS uuid_2, t0.name AS name_3, t0.brand AS brand_4, t0.private AS private_5, t0.temperature AS temperature_6, t0.humidity AS humidity_7, t0.humidification_system AS humidification_system_8, t0.user_id AS user_id_9 FROM humidor t0 WHERE t0.uuid = ? LIMIT 1', array('e2e64173-174b-4109-a3ce-971a1e9d3b56'), array('uuid'))
     (vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1264)
  at Doctrine\DBAL\Connection->executeQuery('SELECT t0.id AS id_1, t0.uuid AS uuid_2, t0.name AS name_3, t0.brand AS brand_4, t0.private AS private_5, t0.temperature AS temperature_6, t0.humidity AS humidity_7, t0.humidification_system AS humidification_system_8, t0.user_id AS user_id_9 FROM humidor t0 WHERE t0.uuid = ? LIMIT 1', array('e2e64173-174b-4109-a3ce-971a1e9d3b56'), array('uuid'))
     (vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:750)
  at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->load(array('uuid' => 'e2e64173-174b-4109-a3ce-971a1e9d3b56'), null, null, array(), null, 1, null)
     (vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:193)
  at Doctrine\ORM\EntityRepository->findOneBy(array('uuid' => 'e2e64173-174b-4109-a3ce-971a1e9d3b56'))
     (vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:311)
  at Doctrine\ORM\EntityRepository->resolveMagicCall('findOneBy', 'Uuid', array('e2e64173-174b-4109-a3ce-971a1e9d3b56'))
     (vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:228)
  at Doctrine\ORM\EntityRepository->__call('findOneByUuid', array('e2e64173-174b-4109-a3ce-971a1e9d3b56'))
     (src/Controller/Account/CigarController.php:73)
  at App\Controller\Account\CigarController->add(object(Request), object(CigarManager), object(HumidorRepository))
     (vendor/symfony/http-kernel/HttpKernel.php:157)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:79)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:195)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public/index.php:22)    

Working code:

// in the repo
    public function findHumidorByUuid(string $uuid): ?Humidor
    {
        $qb = $this->createQueryBuilder('h')
            ->andWhere('h.uuid = :uuid')
            ->setParameter('uuid', $uuid);

        return $qb->getQuery()->getOneOrNullResult();
    }

// in code
// $uuid is 'e2e64173-174b-4109-a3ce-971a1e9d3b56'
$humidor = $humidorRepository->findHumidorByUuid($uuid);

It is linked to Doctrine of course, but as the UidType logic is inside Symfony I opened the issue here
Thank you

@nicolas-grekas
Copy link
Member
nicolas-grekas commented Oct 31, 2020

// $uuid is 'e2e64173-174b-4109-a3ce-971a1e9d3b56'

Shouldn't this be an instance of UuidV4 instead of a plain string?

@94noni
Copy link
Contributor Author
94noni commented Nov 1, 2020

@nicolas-grekas you mean using?

// $uuid is 'e2e64173-174b-4109-a3ce-971a1e9d3b56'
$uuid = Uuid::fromString($uuid);

I will try this, thank you for your answer

@94noni
Copy link
Contributor Author
94noni commented Nov 1, 2020

@nicolas-grekas works fine, many thanks
closing

@94noni 94noni closed this as completed Nov 1, 2020
@lars-feyerabend
Copy link

@nicolas-grekas Hi Nicolas. Even though the original poster closed this thread having found a workaround, I do think he was on to something. I'm currently struggling with a broken ParamConverter on 5.2.0-BETA3, and while I don't fully understand the specifics of it, I think it has to do with your PR #38605. In a standard controller (created via make:crud), the DoctrineParamConverter will not transform the UUID string from the route parameter to a Uid object before passing it to EntityRepository::find. After that, a string won't be accepted any more as input, and the AbstractUidType will throw a conversion exception.

I'm not sure though if this has to be fixed in the ParamConverter, in Doctrine/DBAL, or in the AbstractUidType. I'm also not sure if anything on my project is wonky (if it helps, I'll set up a minimal example to reproduce) - but I only noticed the behavior after upgrading to BETA3. Package versions (excerpt) are as follows:

doctrine/common 3.0.2
doctrine/dbal 2.12.0
doctrine/doctrine-bundle dev-master c19c6a2
doctrine/orm 2.7.4
sensio/framework-extra-bundle v5.6.1
symfony/doctrine-bridge v5.2.0-BETA3
symfony/framework-bundle v5.2.0-BETA3
symfony/orm-pack v2.0.0
symfony/uid v5.2.0-BETA3

@nicolas-grekas
Copy link
Member

Thanks for the feedback @lars-feyerabend, I missed this use case when I submitted #38605
I'm fine reopening to discuss this.

I'm not sure though if this has to be fixed in the ParamConverter, in Doctrine/DBAL, or in the AbstractUidType. I'm also not sure if anything on my project is wonky

Anyone else has an opinion on this? @stof maybe?

@nicolas-grekas nicolas-grekas reopened this Nov 1, 2020
@lars-feyerabend
Copy link

I've looked into this a bit more. Reverting the change in AbstractUidType to be more lenient regarding its input in convertToDatabaseValue would make it consistent with ramsey's implementation in ramsey/uuid-doctrine. It would, however, not be consistent with Doctrine's standard types, which seem to apply the more strict input handling (e. g., see \Doctrine\DBAL\Types\DateImmutableType).

ParamConverters exhibit the same problem for the DateImmutableType (I've set up a test repo here: https://github.com/lars-feyerabend/symfony-issue-38929), the string value from the URL is never converted to DateTimeImmutable.

Also, without a matching type guesser and form type (with a data transformer applied) UUID fields in forms don't work due to the same change. However, when using EntityType to define a relation to a different entity, it works, I guess because the field's value is set to the other entity's getId, which already produces an Uid object.

So I guess if I had to state an opinion, I'd say short-term solution is reverting the change in AbstractUidType, long-term solution is having a deeper look into the relationship between ParamConverter and EntityRepository.

@nicolas-grekas
Copy link
Member

Please try #38986

@fabpot fabpot closed this as completed Nov 5, 2020
fabpot added a commit that referenced this issue Nov 5, 2020
…lues (nicolas-grekas)

This PR was merged into the 5.2-dev branch.

Discussion
----------

[DoctrineBridge] accept converting Uid-as-strings to db-values

| Q             | A
| ------------- | ---
| Branch?       | 5.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #38929
| License       | MIT
| Doc PR        | -

In #38605 I made Uid types stricter by taking inspiration from native Doctrine types. But #38929 (comment) made me realize this doesn't work with ParamConverters. Here is the fix.

Commits
-------

20714d6 [DoctrineBridge] accept converting Uid-as-strings to db-values
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
0