DDC-1698: Inconsistent proxy file name & namespace result in __PHP_Incomplete_Class when unserializing entities #2135

Closed
opened 2026-01-22 13:42:22 +01:00 by admin · 12 comments
Owner

Originally created by @doctrinebot on GitHub (Mar 13, 2012).

Originally assigned to: @Ocramius on GitHub.

Jira issue originally created by user benjamin:

Starting with Doctrine 2.2, the Proxy classes have inconsistent naming with their file name, which raises problems with class autoloading.
For example, a class named Application\Model\User creates the following proxy class:

Application\Proxy\*_CG_*\Application\Model\User

This class is located in the following file:

Application/Proxy/*_CG_*ApplicationModelUser.php

But whe we serialize such an entity, then unserialize it in another session, the framework autoloader expects the class to be located in:

Application/Proxy/*_CG_*/Application/Model/User.php

But it is not.
As a result, a __PHP_Incomplete_Class is created instead of the expected proxy class.

I'm not sure whether this is an intended behavior, but I would assume this is a bug.

Originally created by @doctrinebot on GitHub (Mar 13, 2012). Originally assigned to: @Ocramius on GitHub. Jira issue originally created by user benjamin: Starting with Doctrine 2.2, the Proxy classes have inconsistent naming with their file name, which raises problems with class autoloading. For example, a class named **Application\Model\User** creates the following proxy class: ``` Application\Proxy\*_CG_*\Application\Model\User ``` This class is located in the following file: ``` Application/Proxy/*_CG_*ApplicationModelUser.php ``` But whe we serialize such an entity, then unserialize it in another session, the framework autoloader expects the class to be located in: ``` Application/Proxy/*_CG_*/Application/Model/User.php ``` But it is not. As a result, a __PHP_Incomplete_Class is created instead of the expected proxy class. I'm not sure whether this is an intended behavior, but I would assume this is a bug.
admin added the Improvement label 2026-01-22 13:42:22 +01:00
admin closed this issue 2026-01-22 13:42:22 +01:00
Author
Owner

@doctrinebot commented on GitHub (Mar 13, 2012):

Comment created by benjamin:

It looks like there is an even broader problem with the new CG prefix; the PSR-0 standard for autoloading states that the underscores should be handled this way:

\namespace\package\Class_Name => {...}/namespace/package/Class/Name.php

Which means that in the above example, it could even expect the file to be located in:

Application/Proxy///CG///Application/Model/User.php

... which is far away from the actual location.
Upgrade to 2.2 broke this code, for us.

@doctrinebot commented on GitHub (Mar 13, 2012): Comment created by benjamin: It looks like there is an even broader problem with the new __CG__ prefix; the PSR-0 standard for autoloading states that the underscores should be handled this way: ``` \namespace\package\Class_Name => {...}/namespace/package/Class/Name.php ``` Which means that in the above example, it could even expect the file to be located in: ``` Application/Proxy///CG///Application/Model/User.php ``` ... which is far away from the actual location. Upgrade to 2.2 broke this code, for us.
Author
Owner

@doctrinebot commented on GitHub (Mar 14, 2012):

Comment created by @beberlei:

Proxy classes do not follow PSR-0. For the case unserializing objects we should provide an extra autoloader i guess.

See here how symfony does it https://github.com/doctrine/DoctrineBundle/blob/master/DoctrineBundle.php#L57

@doctrinebot commented on GitHub (Mar 14, 2012): Comment created by @beberlei: Proxy classes do not follow PSR-0. For the case unserializing objects we should provide an extra autoloader i guess. See here how symfony does it https://github.com/doctrine/DoctrineBundle/blob/master/DoctrineBundle.php#L57
Author
Owner

@doctrinebot commented on GitHub (Mar 14, 2012):

Comment created by @beberlei:

See 9b4d60897d and 01381fae1f

@doctrinebot commented on GitHub (Mar 14, 2012): Comment created by @beberlei: See https://github.com/doctrine/doctrine2/commit/9b4d60897dfc7e9b165712428539e694ec596c80 and https://github.com/doctrine/orm-documentation/commit/01381fae1ff3d4944086c7cfe46721925bf6ca15
Author
Owner

@doctrinebot commented on GitHub (Mar 14, 2012):

Comment created by benjamin:

Thanks for the quick fix, Benjamin.
However, I have to admit that I'm not fully happy with the fix, as we (and probably many others) are not using the Doctrine autoloader.
I supposed that the purpose of PSR-0 was precisely not to be tied to a particular autoloader implementation, and this benefit is lost with this version of Doctrine.

You mentioned in the doc that the proxies are not PSR-0 compliant "for implementation reasons"; as this was working fine before 2.2, could you please explain what requirement prevents Doctrine from keeping the previous naming convention?

@doctrinebot commented on GitHub (Mar 14, 2012): Comment created by benjamin: Thanks for the quick fix, Benjamin. However, I have to admit that I'm not fully happy with the fix, as we (and probably many others) are not using the Doctrine autoloader. I supposed that the purpose of PSR-0 was precisely not to be tied to a particular autoloader implementation, and this benefit is lost with this version of Doctrine. You mentioned in the doc that the proxies are not PSR-0 compliant "for implementation reasons"; as this was working fine before 2.2, could you please explain what requirement prevents Doctrine from keeping the previous naming convention?
Author
Owner

@doctrinebot commented on GitHub (Mar 29, 2012):

Comment created by @beberlei:

In 2.1 the proxies are not PSR-0 compatible themselves, however their class naming is simpler.

In 2.2 we changed proxy names so that you can derive the original name of the proxy by searching for the CG flag. This flag obviously contains the __ chars that some PSR autoloaders detect as directory seperators. I agree this is an unfortunate decision, but it was done this way.

I do think however that we can automatically register the proxy atuoloader (if not yet done) in EntityManager#create(). This would hide this fact from developers automatically.

@doctrinebot commented on GitHub (Mar 29, 2012): Comment created by @beberlei: In 2.1 the proxies are not PSR-0 compatible themselves, however their class naming is simpler. In 2.2 we changed proxy names so that you can derive the original name of the proxy by searching for the __CG__ flag. This flag obviously contains the __ chars that some PSR autoloaders detect as directory seperators. I agree this is an unfortunate decision, but it was done this way. I do think however that we can automatically register the proxy atuoloader (if not yet done) in EntityManager#create(). This would hide this fact from developers automatically.
Author
Owner

@doctrinebot commented on GitHub (Oct 29, 2012):

Comment created by benjamin:

@Benjamin Eberlei
In 2.3 we still have to manually call Autoloader::register() before unserializing entities that may contain proxies.
So EntityManager::create() still doesn't register it. Is there a plan to add this feature?

@doctrinebot commented on GitHub (Oct 29, 2012): Comment created by benjamin: @Benjamin Eberlei In 2.3 we still have to manually call Autoloader::register() before unserializing entities that may contain proxies. So EntityManager::create() still doesn't register it. Is there a plan to add this feature?
Author
Owner

@doctrinebot commented on GitHub (Jan 6, 2013):

Comment created by @beberlei:

[~benjamin] Not at the moment, seems too dangerous for me since it might produce race conditions. This should really be done in the bootstrap of the system.

We need to document this though.

@doctrinebot commented on GitHub (Jan 6, 2013): Comment created by @beberlei: [~benjamin] Not at the moment, seems too dangerous for me since it might produce race conditions. This should really be done in the bootstrap of the system. We need to document this though.
Author
Owner

@doctrinebot commented on GitHub (Jan 6, 2013):

Comment created by benjamin:

Ok, thanks for your answer!

@doctrinebot commented on GitHub (Jan 6, 2013): Comment created by benjamin: Ok, thanks for your answer!
Author
Owner

@doctrinebot commented on GitHub (Sep 9, 2013):

Comment created by mnapoli:

Sorry to be a pain, but can the description of the task be updated:

  • Affects Version/s: should show all versions (or none) but not just 2.2, 2.2.1
  • Fix Version/s: should be blank

This is to make it clear that this bug is not resolved (since we are way past v2.2.2).

Thanks

@doctrinebot commented on GitHub (Sep 9, 2013): Comment created by mnapoli: Sorry to be a pain, but can the description of the task be updated: - Affects Version/s: should show all versions (or none) but not just 2.2, 2.2.1 - Fix Version/s: should be blank This is to make it clear that this bug is not resolved (since we are way past v2.2.2). Thanks
Author
Owner

@doctrinebot commented on GitHub (Sep 25, 2013):

Comment created by chawkinsuf:

Some additional documentation about this would be useful. I just spent some considerable time diagnosing an error related to restoring an entity from a cache. I wasn't able to find a mention of the need to call Autoloader::register until I found this page. It was resolved fairly quickly after I found this. For reference, I added this to my bootstrap:

ini*set('unserialize_callback*func', 'proxymissing');
function proxymissing( $name ) {
    if ( preg_match( '/^DoctrineProxies/', $name ) ) {
        \Doctrine\ORM\Proxy\Autoloader::register( PROXYPATH, 'DoctrineProxies' );
    }
}
@doctrinebot commented on GitHub (Sep 25, 2013): Comment created by chawkinsuf: Some additional documentation about this would be useful. I just spent some considerable time diagnosing an error related to restoring an entity from a cache. I wasn't able to find a mention of the need to call Autoloader::register until I found this page. It was resolved fairly quickly after I found this. For reference, I added this to my bootstrap: ``` ini*set('unserialize_callback*func', 'proxymissing'); function proxymissing( $name ) { if ( preg_match( '/^DoctrineProxies/', $name ) ) { \Doctrine\ORM\Proxy\Autoloader::register( PROXYPATH, 'DoctrineProxies' ); } } ```
Author
Owner

@holtkamp commented on GitHub (Jul 5, 2020):

I also encountered this problem when increasing the amount of typed properties of my Entities (possible as of PHP 7.4) which resulted in an error like:

Typed property Domain\Entity\FooEntity::$bar must be an instance of Domain\Entity\BarEntity or null, __PHP_Incomplete_Class used

In the meanwhile the pointer that the proxy directory and namespace should be registered is documented here:

So probably this issue can be closed?

@holtkamp commented on GitHub (Jul 5, 2020): I also encountered this problem when increasing the amount of typed properties of my Entities (possible as of PHP 7.4) which resulted in an error like: ``` Typed property Domain\Entity\FooEntity::$bar must be an instance of Domain\Entity\BarEntity or null, __PHP_Incomplete_Class used ``` In the meanwhile the pointer that the proxy directory and namespace should be registered is documented here: - https://github.com/doctrine/orm/blob/2a98a98cd36e5eb54ad5ff8ca26fc3a30d5a82ff/docs/en/reference/advanced-configuration.rst#auto-generating-proxy-classes - https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/advanced-configuration.html#autoloading-proxies So probably this issue can be closed?
Author
Owner

@beberlei commented on GitHub (Dec 5, 2020):

Closing this as autoloading proxies is documented.

@beberlei commented on GitHub (Dec 5, 2020): Closing this as autoloading proxies is documented.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#2135