doctrine / orm

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

Upgrading from 2.13 => 2.14 breaks 2nd level cache #10905

Open MatthiasKuehneEllerhold opened 1 year ago

MatthiasKuehneEllerhold commented 1 year ago

BC Break Report

We're using laminas/mvc with the these packages:

doctrine/doctrine-laminas-hydrator               3.3.0              Doctrine hydrators for Laminas applications
laminas/laminas-cache                            3.11.0             Caching implementation with a variety of storage options, as well as codified caching strategies for callbacks, classes, and output
laminas/laminas-cache-storage-adapter-blackhole  2.3.0              Laminas cache adapter for blackhole
laminas/laminas-cache-storage-adapter-filesystem 2.3.0              Laminas cache adapter for filesystem
laminas/laminas-cache-storage-adapter-memory     2.2.0              Laminas cache adapter for memory
laminas/laminas-cache-storage-adapter-redis      2.5.0              Laminas cache adapter for redis
laminas/laminas-code                             4.11.0             Extensions to the PHP Reflection API, static code scanning, and code generation
laminas/laminas-config                           3.8.0              provides a nested object property based user interface for accessing this configuration data within application code
laminas/laminas-modulemanager                    2.14.0             Modular application system for laminas-mvc applications
laminas/laminas-mvc                              3.6.1              Laminas's event-driven MVC layer, including MVC Applications, Controllers, 
...
beberlei/doctrineextensions                      v1.3.0             A set of extensions to Doctrine 2 that add support for additional query functions available in MySQL, Oracle, PostgreSQL and SQLite.
doctrine/annotations                             2.0.1              Docblock Annotations Parser
doctrine/cache                                   2.2.0              PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.
doctrine/collections                             2.1.3              PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common                                  3.4.3              PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.
doctrine/dbal                                    3.6.5              Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations                            v1.1.1             A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.
doctrine/doctrine-laminas-hydrator               3.3.0              Doctrine hydrators for Laminas applications
doctrine/doctrine-module                         6.0.4              Laminas Module that provides Doctrine basic functionality required for ORM and ODM modules
doctrine/doctrine-orm-module                     6.0.0              Laminas Module that provides Doctrine ORM functionality
doctrine/event-manager                           1.2.0              The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector                               2.0.8              PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/instantiator                            2.0.0              A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                                   2.1.0              PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                              3.6.0              PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.
doctrine/orm                                     2.16.1             Object-Relational-Mapper for PHP
doctrine/persistence                             3.2.0              The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.

Ive just upgraded the doctrine packages:

  - Upgrading doctrine/cache (1.13.0 => 2.2.0)
  - Upgrading doctrine/collections (1.8.0 => 2.1.3)
  - Upgrading doctrine/doctrine-module (5.3.0 => 6.0.4)
  - Upgrading doctrine/doctrine-orm-module (5.3.0 => 6.0.0)
  - Upgrading doctrine/instantiator (1.5.0 => 2.0.0)
  - Upgrading doctrine/lexer (1.2.3 => 2.1.0)
  - Upgrading doctrine/orm (2.13.5 => 2.16.1)
  - Upgrading laminas/laminas-cache (3.10.1 => 3.11.0)

After this upgrade every page that uses entities in the second level cache are throwing 500, its these errors:

2023-08-10T14:01:44+02:00 ERR (3): Error: Object of class ENTITY1 could not be converted to string in /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php:46
Stack trace:
#0 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php(46): implode(' ', Array)
#1 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php(414): Doctrine\ORM\Cache\EntityCacheKey->__construct('Ellerhold\\...', Array)
#2 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php(215): Doctrine\ORM\Cache\Persister\Entity\AbstractEntityPersister->loadById(Array, Object(DoctrineORMModule\Proxy\__CG__\ENTITY2))
#3 /var/www/data/DoctrineORMModule/Proxy/__CG__ENTITY2.php(197): Doctrine\ORM\Proxy\ProxyFactory->Doctrine\ORM\Proxy\{closure}(Object(DoctrineORMModule\Proxy\__CG__\ENTITY2), 'get', Array)
#4 /var/www/data/DoctrineORMModule/Proxy/__CG__ENTITY2.php(197): Closure->__invoke(Object(DoctrineORMModule\Proxy\__CG__\ENTITY2), 'get', Array)
#5 /var/www/module/ENTITY1.php(222): DoctrineORMModule\Proxy\__CG__\ENTITY2->get()

We are using redis as a backend for this cache

Q A
BC Break yes
Version 2.14, 2.16.0, 2.16.1

Summary

2nd Level caching of entities does not work anymore and leads to error 500.

Previous behavior

Marked entities can be cached and the page is shown correctly.

Current behavior

The error above is logged to the error log and a 500 is displayed.

How to reproduce

#[ORM\Table(name: 'entity')]
#[ORM\Entity(readOnly: true)]
#[ORM\Cache(usage: 'READ_ONLY', region: 'default_region')]
class ENTITY
{
    #[ORM\Id]
    #[ORM\Column(name: 'name', type: 'string', nullable: false, length: 50)]
    protected string $name;

    #[ORM\OneToMany(targetEntity: ENTITY2::class, mappedBy: 'entity1')]
    protected Collection $entities2;

    ...
}

class ENTITY2
{
    #[ORM\Id]
    #[ORM\ManyToOne(targetEntity: ENTITY1::class, inversedBy: 'entities2')]
    #[ORM\JoinColumn(name: 'entity1', referencedColumnName: 'name', nullable: false)]
    protected $entity1;

    #[ORM\Id]
    #[ORM\Column(name: 'string2', type: 'string', length: 50, nullable: false)]
    protected string $string2;

     ...
}
MatthiasKuehneEllerhold commented 1 year ago

Deleting all #[ORM\Cache(...)] attributes fixes the problem but disables the 2nd level cache completely.

mpdude commented 1 year ago

To reproduce, we need the code that leads to the exception being thrown.

Also, can you narrow the range of ORM versions where the break happens? Did it break between 2.13.5 and 2.14.0?

MatthiasKuehneEllerhold commented 1 year ago

Yes it breaks by upgrading from 2.13.5 to 2.14.0.

Ive hoped that the code of the two entities would be enough, but Ill try to provide a complete reproducer.

MatthiasKuehneEllerhold commented 1 year ago

I was finally able to reproduce the issue with a severly cut down version of my project. You can find it here: https://github.com/MatthiasKuehneEllerhold/DoctrineOrm10905

The problem is this (as far as I understand it): Ive got Entity Product and Machine. These are my 2 base entities. Then Ive got 2 relationship entities:

I'm using the field product on product_default_machine for BOTH FKs (to Product and to ProductMachine). In branch possible-fix Ive added another field namend product2 - same problems.

Hopefully you can use this reproducer.

MatthiasKuehneEllerhold commented 11 months ago

Any news? Any way I can help?

MatthiasKuehneEllerhold commented 1 month ago

Still happening with

# composer show | grep doctrine
beberlei/doctrineextensions                      v1.5.0                                        A set of extensions to Doctrine 2 that add support for additional query functions available in MySQL, Oracle, PostgreSQL and SQLite.
doctrine/annotations                             2.0.1                                         Docblock Annotations Parser
doctrine/cache                                   2.2.0                                         PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.
doctrine/collections                             2.2.2                                         PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common                                  3.4.4                                         PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.
doctrine/dbal                                    3.8.6                                         Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations                            1.1.3                                         A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.
doctrine/doctrine-laminas-hydrator               3.4.0                                         Doctrine hydrators for Laminas applications
doctrine/doctrine-module                         6.1.1                                         Laminas Module that provides Doctrine basic functionality required for ORM and ODM modules
doctrine/doctrine-orm-module                     6.1.0                                         Laminas Module that provides Doctrine ORM functionality
doctrine/event-manager                           1.2.0                                         The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector                               2.0.10                                        PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/instantiator                            2.0.0                                         A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                                   3.0.1                                         PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                              3.8.0                                         PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use a...
doctrine/orm                                     2.19.6                                        Object-Relational-Mapper for PHP
doctrine/persistence                             3.3.3                                         The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.