2009-09-18 16 views
30

Dokumentacja PHP mówi: "Nie można używać odwołań w zmiennych sesji, ponieważ nie istnieje żaden możliwy sposób przywrócenia odniesienia do innej zmiennej."Przechowywanie obiektów w sesji PHP

Czy to znaczy, że nie mogą mieć takie rzeczy jak:

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

Próbowałem przechowywać prosty łańcuch i obiektu użytkownika w sesji, ciąg zawsze utrzymuje się pomiędzy stronami do stron lub po odświeżanie strony. Jednak zmienna użytkownika jest tracona w $ _SESSION (staje się pusta).

jakiś pomysł?

Edytuj: Edytuj: Potwierdziłem, że identyfikator sesji jest taki sam na wszystkich tych stronach/podstronach, przed & po odświeżeniu strony.

Edytuj: Edycja: Co dziwne, po tym, jak spróbowałem ponownej translacji i unserializacji poniżej, serializowany obiekt użytkownika (lub ciąg znaków) w sesji nadal znika!

Edycja: W końcu zorientowałem się, co to błąd, wygląda jakoś $ _SESSION ['user'] zostaje nadpisany przez jakąś tajemniczą siłę, jeśli używam jakiejkolwiek zmiennej innej niż "user", wszystko jest w porządku. PHP (przynajmniej wersja 5.3, której używam) dokonuje serializacji i automatycznie się odserializuje po umieszczeniu obiektu w $ _SESSION.

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

sesje PHP może zostać porwany, więc najlepiej, aby nigdy nie przechowuje żadnych informacji o użytkowniku w nich. Zapisałbym identyfikator użytkownika i hashowane hasło w pliku cookie. Następnie, gdy potrzebujesz informacji o użytkowniku, ściągnij z bazy danych (używając identyfikatora zapisanego w pliku cookie), a następnie sprawdź poprawność hasła hash. Jeśli test hash-pass się powiedzie, wypełnij obiekt użytkownika informacjami z bazy danych. – brianreavis

+0

ale to dodaje obciążenie związane z wywoływaniami bazy danych za każdym razem, gdy trzeba pobrać informacje o użytkowniku, zamiast pobierać dane użytkownika raz z bazy danych, a następnie móc z niego korzystać podczas sesji. – user157195

+0

Pewnie, dodaje narzut. Ale czy troszczysz się bardziej o koszty ogólne lub bezpieczeństwo? Możesz * przechowywać * dane użytkownika w sesji *, jeśli * miałeś je potwierdzić (łącząc technikę ciasteczek). Ale na pewno * nie * używaj sesji na oślep. – brianreavis

Odpowiedz

0

To oczekiwanego zachowania. Przechowywanie odniesienia do obiektu działałoby tylko wtedy, gdyby lokalizacja pamięci dla obiektu nie uległa zmianie. W protokole bezstanowym, takim jak HTTP, stan aplikacji nie jest zachowywany między żądaniami. Następne żądanie może być obsługiwane na innym wątku, procesie lub innym serwerze.

Biorąc pod uwagę charakter bezpaństwowy aplikacji internetowej, trzymanie wskaźnika w miejscu pamięci jest bezużyteczne. Dlatego stan obiektu musi być podzielony na format przechowywania, zapisany lub przesłany, a następnie odtworzony w razie potrzeby. Ten proces jest znany jako Serialization.

Można dokonać serializacji całego obiektu w sesji (co może być niebezpieczne w zależności od głębokości wykresu obiektu, ponieważ obiekt może zawierać odniesienia do innych obiektów i te powinny być również serializowane) lub jeśli obiekt można odtworzyć, wysyłając zapytanie do bazy danych przy następnym żądaniu, możesz ukryć identyfikator w sesji.

[EDIT]

JPot podkreślić, że obiekty są automatycznie szeregowane do $ _SESSION, tak wyraźny serializacji nie jest konieczne. Zostawię odpowiedź dla potomności, ale oczywiście nie pomoże to twojemu problemowi.

+0

Implementacja sesji php ma wbudowaną serializację: automatycznie serializuje typy serializowalne (zawiera typy natywne) – JPot

+0

Z dokumentacji PHP: "Jeśli używasz sesji i używasz session_register() do rejestrowania obiektów, te obiekty są serializowane automatycznie na koniec każdej strony PHP i są automatycznie odserializowane na każdej z kolejnych stron. "To sprawia, że ​​brzmi to tak, jakby typy były automatycznie serializowane po zarejestrowaniu. W przeciwnym razie, dokument docs przykład sho w obiekty jawnie serializowane. Czy to jest niedokładne? – gbc

+0

Dokumenty pokazują, że obiekty są jawnie serializowane, ponieważ strona zawiera informacje o serializacji obiektów. Blurb o session_register() jest tylko luźno związany z serializacją. Mówi się w zasadzie, że nie trzeba serializować obiektów jawnie, aby używać ich w sesjach. – JPot

48

Musisz użyć magic __sleep and __wakeup methods dla PHP 5 obiektów.

na przykład w kolejnym bloku kodu:

$obj = new Object(); 

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

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

__sleep jest wywoływana przez serialize(). Metoda sleep zwróci tablicę wartości z obiektu, który chcesz utrwalić.

__wakeup wywoływana jest przez unserialize(). Metoda wybudzania powinna przyjmować niezdyskryminowane wartości i inicjować je w nich w obiekcie.

+1

Noah, czy nie musimy definiować __sleep() i __wakeup() w klasie, to znaczy, czy domyślnie znajdują się w klasie ??? –

+0

@RajeshPaul Myślę, że nie, to są magiczne metody PHP i każda klasa je ma, jak __construct(), __destruct() i tak dalej, więc nie musisz ich definiować ponownie ... – fsasvari

+0

Możesz zdefiniować je, aby je zastąpić domyślny mechanizm serializacji i deserializacji, na przykład do serializacji powiązanych obiektów (odniesionych) wraz z głównym obiektem, a następnie przywracania ich wszystkich później. –

2

Twój przykładowy kod nie używa referencji jako dokumentacja miał na myśli. This is what php means by references:

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

chodzi o oddanie obiektów do sesji PHP może przechowywania obiektów w $_SESSION. Zobacz http://example.preinheimer.com/sessobj.php.

What you are seeing is a bug w kolejności wywołań __sleep i __destruct (__destruct jest wywoływana przed __sleep) oraz moduł sesji nie serializacji obiektu przy wyłączaniu. Ten błąd został otwarty w dniu wrz 1, 2009.

+0

gdzie mogę znaleźć więcej przykładów, takich jak przykład samochodu przedindustrialnego ?! To po prostu niesamowite. – Tim

1

miałeś rację mówiąc, że nie może przechowywać referencje w sesjach zmiennych przypisanie obiektu w PHP 5 i powyżej robi tylko to przypisanie NOT referencyjne OBJ

Że dlaczego musiałbyś serializować obiekt (implementując również __sleep w klasie) i przypisując ciąg do zmiennej sesyjnej

i później przekształcając ją w postać szeregową (wdrażając także __wake w klasie) z późniejszej zmiennej sesji.

0

Dla bezpiecznego serializacji i odserializacji kodowania i dekodowania z base64_encode() i() base64_decode odpowiednio. Poniżej przekazuję serializowany obiekt do sesji i odsyntetyzuję go na drugiej stronie, aby odzyskać zmienną do stanu obiektu.

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

W tym artykule opisano problemy, które mogą być napotykanych przez nie robić. issuses with php serialization/unserialization

Powiązane problemy