Хранение объектов в сеансе PHP
В документации по PHP говорится: "Вы не можете использовать ссылки в переменных сеанса, поскольку нет возможности восстановить ссылку на другую переменную".
Означает ли это, что я не могу иметь такие вещи, как:
session_start();
$user = new User;
$user->name = 'blah';
$_SESSION['user'] = $user;
Я попытался сохранить простую строку и объект User в сеансе, строка всегда сохраняется между страницами на страницы или после обновления страницы. Однако пользовательская переменная теряется в $_SESSION (становится пустой).
любая идея?
Изменить:
Я подтвердил, что session_id одинаково во всех этих страницах/подстраницах, до и после обновления страницы.
Изменить:
Как ни странно, после того, как я попытался выполнить сериализацию и неэтериализованный подход ниже, сериализованный пользовательский объект (или строка) в сеансе все еще исчезает!
Изменить:
наконец, я понял, что это за ошибка, выглядит как-то $_SESSION ['user'], переписывается какой-то таинственной силой, если я использую любую переменную, отличную от "пользователя", тогда все прекрасно. PHP (по крайней мере, 5.3, который является используемой версией) выполняет сериализацию и несериализацию автоматически, когда вы помещаете объект в $_SESSION.
session_start();
$user = new User();
$user->name = 'blah'
$_SESSION['myuser'] = $user;
Ответы
Ответ 1
Для объектов PHP 5 необходимо использовать методы магии __sleep и __wakeup.
Например, в следующем блоке кода:
$obj = new Object();
$_SESSION['obj'] = serialize($obj);
$obj = unserialize($_SESSION['obj']);
__ sleep вызывается serialize(). Метод sleep возвращает массив значений из объекта, который вы хотите сохранить.
__ wakeup вызывается unserialize(). Метод пробуждения должен принимать неэтериализованные значения и инициализировать их в них в объекте.
Ответ 2
В вашем примере кода не используются ссылки, на которые ссылалась документация. Это то, что php означает по ссылкам:
$var =& $GLOBALS["var"];
Что касается помещения объектов в сеанс, PHP может хранить объекты в $_SESSION
. См. http://example.preinheimer.com/sessobj.php.
Что вы видите, это ошибка в порядке вызовов __sleep
и __destruct
(__destruct
) до __sleep
), а модуль сеанса не может сериализовать объект при выключении. Эта ошибка была открыта 1 сентября 2009 года.
Ответ 3
Вы правильно сказали, что не можете хранить ссылки в переменных сеансов
назначение объекта в PHP 5 и выше делает именно это назначение ссылки не obj
Вот почему вам понадобится сериализовать объект (реализующий также __sleep в классе) и присвоение строки переменной сеанса
и десериализуем его позже (также реализуя __wake в классе) из переменной сеанса позже.
Ответ 4
Это ожидаемое поведение. Хранение ссылки на объект будет работать только в том случае, если местоположение памяти для объекта не изменилось. В протоколе без учета состояния, таком как HTTP, состояние приложения не сохраняется между запросами. Следующий запрос может обрабатываться другим потоком, процессом или другим сервером.
Учитывая присущий апатриду характер веб-приложения, удерживание указателя на ячейку памяти бесполезно. Следовательно, состояние объекта должно быть разбито на формат хранения, сохранено или передано, а затем восстановлено, когда это необходимо. Этот процесс известен как Serialization.
Вы можете сериализовать весь объект в сеансе (что может быть опасно в зависимости от глубины вашего графа объектов, поскольку ваш объект может содержать ссылки на другие объекты, и они также должны быть сериализованы), или если объект могут быть восстановлены путем запроса базы данных по следующему запросу, вы можете просто занести идентификатор в сеанс.
[EDIT]
JPot указал, что объекты автоматически сериализуются в $_SESSION, поэтому явная сериализация не требуется. Я оставлю ответ для потомков, но, очевидно, это не поможет вашей проблеме.
Ответ 5
Для безопасной сериализации и несериализации кодируются и декодируются с base64_encode() и base64_decode() соответственно. Ниже я передаю сериализованный объект в сеанс и неэтериализую его на другой странице, чтобы вернуть переменную в состояние объекта.
Page 1
<?php
require $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$registrationData= new RegistrationClass();
$registrationData->setUserRegData();
$reg_serlizer = base64_encode(serialize($registrationData)); //serilize the object to create a string representation
$_SESSION['regSession'] = $reg_serlizer;
?>
Page 2
<?php
session_start();
require $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$reg_unserilizeObj =
unserialize((base64_decode($_SESSION['regSession'])));
$reg_unserilizeObj->firstName;
?>
В этой статье описываются проблемы, с которыми может столкнуться, не делая этого.
isuses с сериализацией /unserialization php