2009-09-18 4 views
30

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

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

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

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

любая идея?

Редактировать: Я подтвердил, что session_id одинаково во всех этих страницах/подстраницах, до & после обновления страницы.

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

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

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

Сессии PHP могут быть угнаны, поэтому лучше никогда не хранить информацию о пользователях в них. Я бы сохранил идентификатор пользователя и hashed пароль в cookie. Затем, когда вам нужна информация о пользователе, вытащите из своей базы данных (используя идентификатор, хранящийся в файле cookie), а затем проверьте хэш пароля. Если хеш-чек проходит, заполните свой пользовательский объект информацией из базы данных. – brianreavis

+0

, но при этом каждый раз, когда вам нужно собирать информацию о пользователе, каждый раз добавляет накладные расходы на вызовы базы данных, вместо того, чтобы извлекать информацию о пользователя из базы данных, а затем использовать ее через сеанс. – user157195

+0

Несомненно, он добавляет накладные расходы. Но вам больше не нужны дополнительные накладные расходы или безопасность? Вы * можете * хранить пользовательские данные в сеансе *, если * вы должны были проверить его (путем соединения техники cookie). Но, конечно, не используйте сеансы слепо. – brianreavis

ответ

0

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

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

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

[EDIT]

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

+0

Реализация сессии php имеет встроенную сериализацию: она автоматически сериализует сериализуемые типы (включая собственные типы). – JPot

+0

Из документов PHP: «Если вы используете сеансы и используете session_register() для регистрации объектов, эти объекты сериализуются автоматически в конец каждой страницы PHP и автоматически несериализуются на каждой из следующих страниц ». Это заставляет его звучать так, как если бы типы были автоматически отсортированы по типу, иначе пример docs w объекты явно сериализованы. Это неточно? – gbc

+0

Документы показывают, что объекты явно сериализованы, потому что эта страница посвящена сериализации объектов. Разметка о session_register() привязана только к сериализации. Говорят, в основном вам не нужно сериализовывать объекты явно, чтобы использовать их в сеансах. – JPot

48

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

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

$obj = new Object(); 

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

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

__sleep вызывается сериализации(). Метод sleep возвращает массив значений из объекта, который вы хотите сохранить.

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

+1

Noah, не надо ли нам определять __sleep() и __wakeup() в классе, я имею в виду, что они по-прежнему проживают в классе ??? –

+0

@RajeshPaul Я думаю, что нет, это волшебные методы PHP, и каждый класс имеет их, например __construct(), __destruct() и т. Д., Поэтому вам не нужно их снова определять ... – fsasvari

+0

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

2

Ваш код не использует ссылки, на которые ссылается документация. This is what php means by references:

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

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

What you are seeing is a bug в порядке обращений к __sleep и __destruct (__destruct вызывается перед тем __sleep) и модуль сеанса не удается сериализовать объект при выключении. Эта ошибка была открыта 1 сентября 2009 года

+0

Где я могу найти больше примеров, например, пример автомобиля в преинхаймере ?! Это просто потрясающе. – Tim

1

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

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

и десериализация ее позже (реализация также __wake в классе) из переменной сеанса позже.

0

Для безопасной сериализации и несериализации кодирование и декодирование с помощью 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; 
?> 

В данной статье описываются проблемы, с которыми могут столкнуться, не делая так. issuses with php serialization/unserialization

Смежные вопросы