Хранение объектов в PHP сессии - PullRequest
30 голосов
/ 18 сентября 2009

Документация PHP гласит: «Вы не можете использовать ссылки в переменных сеанса, поскольку не существует реального способа восстановить ссылку на другую переменную».

Означает ли это, что я не могу иметь такие вещи, как:

session_start();
$user = new User;
$user->name = 'blah';
$_SESSION['user'] = $user;

Я пытался сохранить простую строку и объект User в сеансе, строка всегда сохраняется между страницами или после обновления страницы. Однако переменная User теряется в $ _SESSION (становится пустой).

есть идеи?

Edit: Я подтвердил, что идентификатор_ сеанса одинаков во всех этих страницах / подстраницах до и после обновления страницы.

Edit: Как ни странно, после того, как я попробовал сериализовать и десериализовать подход ниже, сериализованный объект пользователя (или строка) в сеансе все еще исчезает!

Edit: наконец, я понял, что это за ошибка, похоже, что $ _SESSION ['user'] перезаписывается какой-то таинственной силой, если я использую любую переменную, кроме 'user', то все в порядке. PHP (по крайней мере, версия 5.3, которую я использую) выполняет сериализацию и десериализацию автоматически, когда вы помещаете объект в $ _SESSION.

session_start();
$user = new User();
$user->name = 'blah'
$_SESSION['myuser'] = $user; 

Ответы [ 5 ]

50 голосов
/ 18 сентября 2009

Вам необходимо использовать magic __sleep и __wakeup методы для объектов PHP 5.

Например, в следующем блоке кода:

$obj = new Object();

$_SESSION['obj'] = serialize($obj);

$obj = unserialize($_SESSION['obj']);

__ sleep вызывается serialize (). Спящий метод возвращает массив значений из объекта, который вы хотите сохранить.

__ wakeup вызывается unserialize (). Метод пробуждения должен принимать несериализованные значения и инициализировать их в них в объекте.

2 голосов
/ 18 сентября 2009

Ваш пример кода не использует ссылки, как ссылалась документация. Это то, что php подразумевает под ссылками :

$var =& $GLOBALS["var"];

Что касается помещения объектов в сеанс, PHP может хранить объекты в $_SESSION. Смотри http://example.preinheimer.com/sessobj.php.

Вы видите ошибку в порядке вызовов __sleep и __destruct (__destruct вызывается до __sleep), и модуль сеанса не может сериализовать объект при выключении. Эта ошибка была открыта 1 сентября 2009 года.

1 голос
/ 29 ноября 2017

Для безопасной сериализации и десериализации кодируйте и декодируйте с base64_encode () и base64_decode () соответственно. Ниже я передаю сериализованный объект в сеанс и десериализую его на другой странице, чтобы вернуть переменную в состояние объекта.

Страница 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;
?>

Страница 2

<?php
session_start();
require  $_SERVER['DOCUMENT_ROOT'] .'/classes/RegistrationClass.php';
$reg_unserilizeObj = 
unserialize((base64_decode($_SESSION['regSession'])));
$reg_unserilizeObj->firstName;
?>

В этой статье описываются проблемы, с которыми можно столкнуться, если этого не сделать. выдает с сериализацией / десериализацией php

1 голос
/ 18 июня 2013

Вы были правы, говоря, что вы не можете хранить ссылки в переменных сессий назначение объекта в PHP 5 и более поздних версиях - это просто назначение ссылки, а не объекта obj

Вот почему вам необходимо сериализовать объект (реализуя также __sleep в классе) и присвоить строку переменной сеанса

и десериализацию его позже (реализуя также __wake in the Class) из переменной сеанса позже.

0 голосов
/ 18 сентября 2009

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

Учитывая природу веб-приложения без сохранения состояния, указатель на область памяти бесполезен. Поэтому состояние объекта должно быть разбито на формат хранения, сохранено или передано, а затем восстановлено при необходимости. Этот процесс известен как Сериализация .

Вы можете выбрать сериализацию всего объекта в сеанс (что может быть опасно в зависимости от глубины графа вашего объекта, поскольку ваш объект может содержать ссылки на другие объекты, и их также необходимо сериализовать), или если объект можно восстановить, запросив базу данных при следующем запросе, вы можете просто спрятать идентификатор в сеансе.

[EDIT]

JPot указал, что объекты автоматически сериализуются в $ _SESSION, поэтому явная сериализация не требуется. Я оставлю ответ для потомков, но, очевидно, он не поможет вашей проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...