Why can't I store a PHP class instance as a SE

2019-04-30 19:13发布

问题:

I have a PHP script that is called in 2 ways from a Dojo Ajax xhrGet call. The first time it is called with an "init" argument which causes the script to create an instance of the StateList class and read in a file of state names.

session_start();
@include('StateList.php');
require_once('phplog.php');

//start executing here
$comd=$_GET['nexturl'];
if($comd=="init") {
$st = new StateList("../data/statestxt.txt");
$_SESSION['statefile'] = $st;
}

The second and further times, another xhrGet call passes a "getstate" argument and the following code tries to get the instance ofr the StateList class from the SESSION array.

if($comd =="getstate") {
$st= $_SESSION['statefile'];
phplog("size=".$st->getSize());

}

However, the getSize() method is never executed, nor can I call any other method on the reconstituted StateList class instance.

Note that this is one PHP script that DOES include the class definition at the top and thus the class methods should be known and avaialble.

What am I missing here?

回答1:

You need to include the class definition before you call session_start(), otherwise the object will not be deserialized correctly and will be an instance of __PHP_Incomplete_Class. Otherwise what you have should work fine.



回答2:

You may need to serialize the $st object/variable before you store it. This will ensure that everything is saved to the session. This is definitely the way to go for object oriented code. When you want to use the data again, you must unserialize it.



回答3:

This is one of those things that's hard to debug in isolation. Storing instantiated objects in PHP Sessions is always a little tricky, and not 100% guaranteed to work. Here's some general debugging tips that may help you figure this out.

First, check your apache error log. Are you getting a "method called on non-object error"? If so, this means you're not getting an object back out of the session. If not, is there an error that indicated your method call is failing for another reason?

Second, check to see what you're really getting out of your session.

if($comd =="getstate") {
    $st= $_SESSION['statefile'];
    //get the class of st
    phplog("instance=".get_class($st));

    //get a reflection dump of st
    $ref = new ReflectionClass($st);
    $string = $ref->__toString();       
    phplog("reflection=".$string);
}   

Third, look at the serialized string value that is being stored in the session itself. Are you actually storing a serialized object? In your dev environment, set the session.save_path ini value in php.ini to something like /tmp, (or use the ini_set method to do the same thing):

session.save_path = "/tmp"

and then examine the files created in /tmp (or whatever folder). You should see a string that starts with:

statefile:O:..........

The name of the class that instantiated the object will also be included in there, as well as values saved to properties.



回答4:

If you are going to store an object in the session it must be link text.There are a LOT of problems with serializing objects in PHP, let alone storing them in the session. I recommend against doing this altogether, and finding a different solution for your problem. If you are going to do it though, you should look into the 'magic methods' link text which you should define in your class to facilitate it's reinstantiation when it is called from the session.



回答5:

Do you have session.auto_start enabled? The manual's session page states that if you do, you have to load the class definition differently:

If you turn on session.auto_start then the only way to put objects into your sessions is to load its class definition using auto_prepend_file in which you load the class definition else you will have to serialize your object and unserialize it afterwards.

http://php.net/manual/en/intro.session.php

As that page says, the serialization/unserialization of the object will normally be done automatically by PHP, but having session.auto_start enabled will change this.



回答6:

Try this:

    include('StateList.php');
    require_once('phplog.php');
    // start your session after including your class file
    session_start();

    //start executing here
    $comd=$_GET['nexturl'];
    if($comd=="init") {
    $st = new StateList("../data/statestxt.txt");
    $_SESSION['statefile'] = $st;
    } 

    if($comd =="getstate") {
    // the ampersand creates a reference, preserving any further changes to your session data
    $st = &$_SESSION['statefile'];
    phplog("size=".$st->getSize());
    }