Почему я не могу сохранить экземпляр класса PHP как переменную SESSION - PullRequest
5 голосов
/ 02 марта 2009

У меня есть PHP-скрипт, который вызывается двумя способами из вызова Dojo Ajax xhrGet. Первый раз он вызывается с аргументом «init», который заставляет сценарий создать экземпляр класса StateList и прочитать файл имен состояний.

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;
}

Во второй и последующий раз другой вызов xhrGet передает аргумент getstate, а следующий код пытается получить экземпляр класса StateList из массива SESSION.

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

}

Однако метод getSize () никогда не выполняется, и я не могу вызвать любой другой метод в восстановленном экземпляре класса StateList.

Обратите внимание, что это один скрипт PHP, который включает определение класса вверху и, таким образом, методы класса должны быть известны и доступны.

Что мне здесь не хватает?

Ответы [ 6 ]

13 голосов
/ 02 марта 2009

Вам необходимо включить определение класса перед вызовом session_start(), иначе объект не будет правильно десериализован и будет экземпляром __PHP_Incomplete_Class. В противном случае то, что у вас есть, должно работать нормально.

1 голос
/ 02 марта 2009

Это одна из тех вещей, которые трудно отлаживать в изоляции. Хранение экземпляров объектов в PHP-сессиях всегда немного сложно, и не гарантируется 100% -ная работа. Вот несколько общих советов по отладке, которые могут помочь вам разобраться в этом.

Сначала проверьте журнал ошибок Apache. Вы получаете "метод, вызванный при ошибке необъектного объекта"? Если это так, это означает, что вы не получаете объект обратно из сеанса. Если нет, есть ли ошибка, указывающая на сбой вызова метода по другой причине?

Во-вторых, проверьте, что вы действительно получаете от своей сессии.

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);
}   

В-третьих, посмотрите на сериализованное строковое значение, которое хранится в самом сеансе. Вы на самом деле храните сериализованный объект? В вашей среде разработки установите значение ini для session.save_path в php.ini, например, в / tmp (или используйте метод ini_set для того же):

session.save_path = "/tmp"

и затем проверьте файлы, созданные в / tmp (или любой другой папке). Вы должны увидеть строку, которая начинается с:

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

Имя класса, в котором был создан объект, также будет включено туда, а также значения, сохраненные в свойствах.

1 голос
/ 02 марта 2009

Вам может потребоваться сериализовать объект / переменную $ st перед сохранением. Это обеспечит сохранение всего в сеансе. Это определенно способ пойти для объектно-ориентированного кода. Если вы хотите снова использовать данные, вы должны отменить сериализацию их.

0 голосов
/ 29 марта 2012

Попробуйте это:

    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());
    }
0 голосов
/ 02 марта 2009

У вас есть session.auto_start включен? Страница сеанса руководства гласит, что если вы это сделаете, вы должны загрузить определение класса по-другому:

Если вы включите session.auto_start, то единственный способ поместить объекты в ваши сеансы - это загрузить определение его класса, используя auto_prepend_file, в котором вы загрузите определение класса, иначе вам придется сериализовать ваш объект и впоследствии его сериализовать.

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

Как сказано на этой странице, сериализация / десериализация объекта обычно выполняется автоматически PHP, но включение session.auto_start изменит это.

0 голосов
/ 02 марта 2009

Если вы собираетесь хранить объект в сеансе, это должно быть текст ссылки . Существует множество проблем с сериализацией объектов в PHP, не говоря уже о сохранении их в сеансе. Я рекомендую не делать этого вообще, и найти другое решение для вашей проблемы. Однако, если вы собираетесь это сделать, вам следует взглянуть на «магические методы» текст ссылки , которые вы должны определить в своем классе, чтобы упростить его повторное создание при вызове из сеанса.

...