Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-3120

Warning: Erroneous data format for unserializing PHP5.6+

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: Git Master
    • Fix Version/s: 2.5, 2.4.3
    • Component/s: ORM
    • Security Level: All
    • Labels:
    • Environment:
      Webserver Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.6.0beta2

      and

      PHP-CLI (Win32) PHP/5.6.0beta2

      Description

      Hi all,

      There seems to be something strange going on in the method newInstance() of the class \Doctrine\ORM\Mapping\ClassMetadataInfo.

      The original class method looks like this:

      \Doctrine\ORM\Mapping\ClassMetadataInfo#newInstance()

          {
              if ($this->_prototype === null) {
                  $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
              }
      
              return clone $this->_prototype;
          }
      

      What happens now when a class that implements \Serializable is that a "Warning: Erroneous data format for unserializing" shows up and the function unserialize() returns false.

      That is because a class that implements \Serializable is expected to have the letter 'C' in the serialize string instead of the letter 'O'.

      I've made a quick work-around like this:

      \Doctrine\ORM\Mapping\ClassMetadataInfo#newInstance()

          {
              if ($this->_prototype === null) {
                  $this->_prototype = @unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
                  if ($this->_prototype === false) {
                      $this->_prototype = unserialize(sprintf('C:%d:"%s":0:{}', strlen($this->name), $this->name));
                  }
              }
      
              return clone $this->_prototype;
          }
      

      That seems to work in my isolated tests and with Symfony2 and Doctrine2 and FOSUserBundle together.

      I've noticed this because the Model\User class from FOSUserBundle implements \Serializable.

      I had to implement a check in Model\User class because when using 'C:%d:"%s":0:{}' the $serialized parameter of the unserialize method in the Model\User class is a empty string then.

      That warning seems only to happen with PHP5.6+. PHP5.5.12 and below doesn't show that warning.

      I hope someone can shine some light on this, thank you,

      Cornelis.

        Activity

        Hide
        Jovan Perovic added a comment -

        I'm still seeing this bug, although my PHP_VERSION_ID is 50600

        So, version based condition is no good...

        Show
        Jovan Perovic added a comment - I'm still seeing this bug, although my PHP_VERSION_ID is 50600 So, version based condition is no good...
        Hide
        Marco Pivetta added a comment -

        The approach to be taken for 50600 is still under discussion in php-internals.

        Show
        Marco Pivetta added a comment - The approach to be taken for 50600 is still under discussion in php-internals.
        Hide
        Cornelis Brouwers added a comment -

        Hi all,

        I've just downloaded PHP5.6RC1 and updated doctrine and the error is back indeed.

        A little peek at the code starting on line 866 of file Doctrine\ORM\Mapping\ClassMetadataInfo.php shows this:

            public function newInstance()
            {
                if ($this->_prototype === null) {
                    if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) {
                        $this->_prototype = $this->reflClass->newInstanceWithoutConstructor();
                    } else {
                        $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
                    }
                }
        
                return clone $this->_prototype;
            }
        

        As can be seen, PHP5.6 is out of the picture, it only checks for the exact versions 5.4.29 and 5.5.13.

        So for the code to work correctly on PHP5.6 one can add PHP5.6 to the test condition, or just skip the test all together if you don't mind the old PHP5.3. According to PHP, ReflectionClass::newInstanceWithoutConstructor is available since PHP >= 5.4.0.

        Greetings, Cornelis.

        Show
        Cornelis Brouwers added a comment - Hi all, I've just downloaded PHP5.6RC1 and updated doctrine and the error is back indeed. A little peek at the code starting on line 866 of file Doctrine\ORM\Mapping\ClassMetadataInfo.php shows this: public function newInstance() { if ($ this ->_prototype === null ) { if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) { $ this ->_prototype = $ this ->reflClass->newInstanceWithoutConstructor(); } else { $ this ->_prototype = unserialize(sprintf('O:%d: "%s" :0:{}', strlen($ this ->name), $ this ->name)); } } return clone $ this ->_prototype; } As can be seen, PHP5.6 is out of the picture, it only checks for the exact versions 5.4.29 and 5.5.13 . So for the code to work correctly on PHP5.6 one can add PHP5.6 to the test condition, or just skip the test all together if you don't mind the old PHP5.3 . According to PHP, ReflectionClass::newInstanceWithoutConstructor is available since PHP >= 5.4.0 . Greetings, Cornelis.
        Hide
        Marco Pivetta added a comment -

        As I already pointed out, this is still being discussed in php internals. See http://news.php.net/php.internals/75009

        This won't be dealt with in 5.6 until there's either a stable release or internals decides what has to be done.

        Show
        Marco Pivetta added a comment - As I already pointed out, this is still being discussed in php internals. See http://news.php.net/php.internals/75009 This won't be dealt with in 5.6 until there's either a stable release or internals decides what has to be done.
        Hide
        Marco Pivetta added a comment -

        Also, ReflectionClass#newInstanceWithoutConstructor() still doesn't cover the pre-existing "hack" using unserialize, so we're still waiting for a reliable API from PHP core.

        Show
        Marco Pivetta added a comment - Also, ReflectionClass#newInstanceWithoutConstructor() still doesn't cover the pre-existing "hack" using unserialize , so we're still waiting for a reliable API from PHP core.

          People

          • Assignee:
            Marco Pivetta
            Reporter:
            Cornelis Brouwers
          • Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: