Ocramius / ProxyManager

🎩✨🌈 OOP Proxy wrappers/utilities - generates and manages proxies of your objects
MIT License
4.95k stars 188 forks source link

initializeProxy must be compatible with Doctrine #378

Closed phpguru closed 7 years ago

phpguru commented 7 years ago

Trying to deploy Symfony3 project on Ubuntu with PHP 7.1

PHP Fatal error:  Declaration of DoctrineORMEntityManager_000000004025448d000000005ae5af7cccefc00df70107613b44fbd8e9c15cf3::initializeProxy() must be compatible with ProxyManager\\Proxy\\LazyLoadingInterface::initializeProxy(): bool in /var/www/production/releases/20170717122400/var/cache/prod/appProdProjectContainer.php on line 5126

I'm not sure what versions I am supposed to be using.

Here is my composer.json

"require": {
    "php": ">=5.5.9",
    "symfony/symfony": "3.1.*",
    "doctrine/orm": "^2.5",
    "doctrine/doctrine-bundle": "^1.6",
    "doctrine/doctrine-cache-bundle": "^1.2",
    "symfony/swiftmailer-bundle": "^2.3",
    "symfony/monolog-bundle": "^2.8",
    "symfony/polyfill-apcu": "^1.0",
    "sensio/distribution-bundle": "^5.0",
    "sensio/framework-extra-bundle": "^3.0.2",
    "incenteev/composer-parameter-handler": "^2.0",
    "friendsofsymfony/user-bundle": "dev-master",
    "avanzu/admin-theme-bundle": "^1.3",
    "mashape/unirest-php": "2.*",
    "deployer/deployer": "~3.0",
    "deployer/phpseclib":"1.*",
    "beberlei/DoctrineExtensions": "^1.0",
    "twig/extensions": "~1.2",
    "knplabs/knp-paginator-bundle": "^2.5",
    "snilius/twig-sort-by-field": "^0.1.5",
    "jmose/command-scheduler-bundle": "~1.2.2",
    "sensio/generator-bundle": "^3.0",
    "symfony/phpunit-bridge": "^3.0",
    "doctrine/doctrine-migrations-bundle": "^1.0",
    "ocramius/proxy-manager": "^2.1",
    "doctrine/common": "^2.6"
  },

When I remove ": bool" from the two methods in vendor/ocramius/proxy-manager/src/ProxyManager/Proxy/LazyLoadingInterface.php it works fine.

Ocramius commented 7 years ago

Did you upgrade ProxyManager without re-generating your proxies?

phpguru commented 7 years ago

I'm not 100% sure exactly what you mean. I tried several different versions, deleted vendor/ocramius/proxy-manager and did a composer install again, but it kept complaining.

Ocramius commented 7 years ago

it kept complaining.

in /var/www/production/releases/20170717122400/var/cache/prod/appProdProjectContainer.php

Re-dump your container after changing ProxyManager version.

phpguru commented 7 years ago

If you mean to php bin/console cache:clear and composer dump-autoload yes I've done that. The code gets rebuilt with ": bool" return type hinting that is incompatible with the doctrine class.

Ocramius commented 7 years ago

that is incompatible with the doctrine class.

Can you clarify?

Ocramius commented 7 years ago

Is this supposed to be closed?

phpguru commented 7 years ago

Weird, no. It's been awhile since I did a cross-fork PR on Github.

When Symfony builds the appProdContainer, one of two files Symfony builds upon first run after cache clear, it creates this method...

public function initializeProxy()
{
    return $this->initializer596d2cc00ac8c163190862 && $this->initializer596d2cc00ac8c163190862->__invoke($this->valueHolder596d2cc00ac84017495121, $this, 'initializeProxy', array(), $this->initializer596d2cc00ac8c163190862);
}

Your LazyLoading class contains this method signature:

public function intializeProxy() : bool 
{
}

The " : bool" in your class is causing a fatal error, for my combination of Doctrine, PHP 7.1, ubuntu. I manually removed " : bool" from those two methods and the error went away.

phpguru commented 7 years ago

I created a PR.

Ocramius commented 7 years ago

Are you running all environments with the same locked dependencies?

On 19 Jul 2017 7:38 PM, "Geoffrey Hoffman" notifications@github.com wrote:

Weird, no. It's been awhile since I did a cross-fork PR on Github.

When Symfony builds the appProdContainer, one of two files Symfony builds upon first run after cache clear http://oro-quickies.alanstorm.com/symfonys-two-generated-php-files/index.html, it creates this method...

public function initializeProxy() { return $this->initializer596d2cc00ac8c163190862 && $this->initializer596d2cc00ac8c163190862->__invoke($this->valueHolder596d2cc00ac84017495121, $this, 'initializeProxy', array(), $this->initializer596d2cc00ac8c163190862); }

Your LazyLoading class contains this method signature:

public function intializeProxy() : bool { }

The " : bool" in your class is causing a fatal error, for my combination of Doctrine, PHP 7.1, ubuntu. I manually removed " : bool" from those two methods and the error went away.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/Ocramius/ProxyManager/issues/378#issuecomment-316461884, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakDblCcFwEiFLmX89O3kJuhBstq2zks5sPj8EgaJpZM4Oaola .

phpguru commented 7 years ago

I believe so... meaning composer.json & composer.lock is the same, and doing composer install?

phpguru commented 7 years ago

Ok weird, in my appDevDebugProjectContainer built on Mac dev environment, the method signature is

public function initializeProxy() : bool
{
 }

So I'm not sure what's going on when I deploy the project in production on Ubuntu. It could also be a difference between coercive (in dev) and strict (in prod) type declarations. It's not clear.

Ocramius commented 7 years ago

The signature of the generated code should have the return type

On 19 Jul 2017 7:49 PM, "Geoffrey Hoffman" notifications@github.com wrote:

Ok weird, in my appDevDebugProjectContainer built on Mac dev environment, the method signature is

public function initializeProxy() : bool { }

So I'm not sure what's going on when I deploy the project in production on Ubuntu. It could also be a difference between coercive (in dev) and strict (in prod) type declarations. It's not clear.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/Ocramius/ProxyManager/issues/378#issuecomment-316464887, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakBLX1PDW_9Po7pF8ZMGx4Z87mw77ks5sPkGqgaJpZM4Oaola .

phpguru commented 7 years ago

Yeah, that much has become clear, and it's working fine on Mac with PHP 7.0.20. It's not clear why the appProdProjectContainer.php is not built correctly for me, but it's not an issue with ProxyManager. Thanks for your help.

Ocramius commented 7 years ago

@phpguru to clarify, the return type is generated here: https://github.com/Ocramius/ProxyManager/blob/5c8c273a171c58a432d990394f183d77685adb0b/src/ProxyManager/ProxyGenerator/LazyLoadingValueHolder/MethodGenerator/InitializeProxy.php#L47

fishbone1 commented 4 years ago

This could be caused by an error in older Symfony versions. I don't know if it still exists.

Symfony should invoke PhpDumper to generate appProdProjectContainer.php. However, it checks if there is a cached version before and uses it instead of generating it. If the cached file was generated by an older version of ProxyManager, it doesn't contain the return type yet and therefore PHP crashes.

If debug is disabled, it doesn't even check if this cached version is up to date:

https://github.com/symfony/symfony/blob/67948a7ffb88fb6146ad57e12a745dbd9341a592/src/Symfony/Component/HttpKernel/Kernel.php#L435

But I'm sure I also could re-produce this without the --no-debug flag. This causes a more complex check if this cached file is "fresh" and I guess it didn't/doesn't work correctly as well.

Ocramius commented 4 years ago

Symfony should invoke PhpDumper to generate appProdProjectContainer.php. However, it checks if there is a cached version before and uses it instead of generating it. If the cached file was generated by an older version of ProxyManager, it doesn't contain the return type yet and therefore PHP crashes.

ProxyManager is designed to invalidate all pre-existing proxy classes at each differing version of the library:

https://github.com/Ocramius/ProxyManager/blob/ac1dd414fd114cfc0da9930e0ab46063c2f5e62a/src/ProxyManager/Factory/AbstractBaseFactory.php#L65-L74

I think symfony cache should consider a hash of installed.json to determine if a cache should be slammed (probably already the case, but not sure)