doctrine / orm

Doctrine Object Relational Mapper (ORM)
https://www.doctrine-project.org/projects/orm.html
MIT License
9.86k stars 2.5k forks source link

Custom types converted to database value by __toString() in loadAll instead of Type::convertToDatabaseValue() #11405

Open hlib-kuznetsov opened 3 months ago

hlib-kuznetsov commented 3 months ago

Bug Report

Q A
BC Break idk
Version 3.1.1

Summary

When eager relations are loaded by BasicEntityPersister::loadAll() https://github.com/doctrine/orm/blob/cbb6c897de4dd4e215c7005505b381c5927e5f4a/src/Persisters/Entity/BasicEntityPersister.php#L907

There only 3 options for array type - STRING, INTEGER and ASCII https://github.com/doctrine/orm/blob/cbb6c897de4dd4e215c7005505b381c5927e5f4a/src/Persisters/Entity/BasicEntityPersister.php#L1908-L1912

So any custom type will be narrowed to one of those types, based on Type::getBindingType() or will fail.

var_dump($criteria);
[$params, $types] = $this->expandParameters($criteria);
var_dump($params, $types);
array(1) {
  [0]=>
  array(1) {
    [0]=>
    object(Symfony\Component\Uid\Ulid)#814 (1) {
      ["uid":protected]=>
      string(26) "01HKQA3CFEMF71KWYC3QN7W87K"
    }
  }
}
array(1) {
  [0]=>
  enum(Doctrine\DBAL\ArrayParameterType::STRING)
}

Then when \Doctrine\DBAL\Connection binds values using Type::convertToDatabaseValue() any custom type, including Symfony\Uuid will be converted using STRING, INTEGER or ASCII convertToDatabaseValue(), not the type's one.

Current behavior

Eager relations refering to custom types are not loaded which leads to additional lazy queries

How to reproduce

Try eager loading when relation refers to column with any custom type, including uuid

Expected behavior

Custom types are bound to statement using convertToDatabaseValue(), not using __toString()

beberlei commented 3 months ago

Could this be related to new eager loading of one to many associations?

michanismus commented 3 months ago

Same for me and my custom Uuid implementation. Database type is binary and the php type is a string. Relations with EAGER loading will always return an empty result. The parameter type is string without being converted to real binary database representation.

Last working version for me: 2.16.3

pauci commented 2 months ago

I'm affected by this issue too. With database type integer, mapped to custom value object PurchaseId, I'm getting error Object of class PurchaseId could not be converted to int

Stuck on 2.16.3