php / doc-en

English PHP documentation
500 stars 729 forks source link

using enum in $_SESSION variable causes session_start to error "Failed to decode session object. " #1481

Open RLievaart opened 2 years ago

RLievaart commented 2 years ago

Description

The following code:

<?php
session_start() ;

enum xxx {
   case A;
   case B;
   case C;
}

echo "Hallo, wereld" ;

$_SESSION['test'] = xxx::C;

When run TWICE!

Resulted SECOND TIME RUNNING in this output:

Warning: session_start(): Class 'xxx' not found in /home/admin/domains/xxxxxxxxx.nl/public_html/test/test.php on line 3

Warning: session_start(): Failed to decode session object. Session has been destroyed in /home/admin/domains/xxxxxxxxxxxx.nl/public_html/test/test.php on line 3
Hallo, wereld

But I expected this output instead:

Hallo, wereld

PHP Version

8.1.4

Operating System

Linux CentOs 7 -- 3.10.0-1160.59.1.el7.x86_64 php/php-src#1 SMP Wed Feb 23 16:47:03 UTC 2022 x86_64

iluuu1994 commented 2 years ago

Enums are a little different than objects in that they don't support session_start() when the enum has not yet been defined. For other objects, PHP would create a __PHP_Incomplete_Class instance. To fix this error, make sure the enum is either loaded or autoloadable when you call session_start().

I don't think this is properly documented so I'm converting this to a documentation issue.

RLievaart commented 2 years ago

Enums are a little different than objects in that they don't support session_start() when the enum has not yet been defined. For other objects, PHP would create a __PHP_Incomplete_Class instance. To fix this error, make sure the enum is either loaded or autoloadable when you call session_start().

I don't think this is properly documented so I'm converting this to a documentation issue.

Thank you for explaining, there was nothing to find on either Google or php.net.

RLievaart commented 2 years ago

I just discovered: enums should be treated as classes when it comes to sessions. I.e. serialized. Especially since they can have methods.

This works fine:


<?php
session_start() ;

enum xxx {
   case A;
   case B;
   case C;
   function hello() {
       echo "Hallo wereld";
   }
}

if ( ! isset($_SESSION['test']) ) {
   $_SESSION['test'] = serialize(xxx::C);
   echo "Set.";
}
else {
   $x = unserialize($_SESSION['test']) ;
   echo $x == xxx::C ? "It's xxx::C\n" : "It's not xxx::C\n" ;
   unserialize($_SESSION['test'])->hello() ;
   unset($_SESSION['test']);
   echo "Unset.";
}

Once this is documented, things will be clearer. Thank you for responding.

iluuu1994 commented 2 years ago

We'll keep this open until it's documented :slightly_smiling_face:

RLievaart commented 2 years ago

Ahhh, I apparantly pressed the wrong button, sorry!