Dziś jest poniedziałek, 13 października 2008 roku (z kalendarza...)

Zend_Session

Icon

26.03.2007, 10:19

PHP

Komentarze (3)

Powrót

Próbowałem dzisiaj wykorzystać klasę Zend_Session z Zend Frameworka wspomaganą własnym adapterem, dzięki któremu możliwe byłoby przechowywanie danych sesji w bazie danych. O ile użytkowanie API do manipulacji danymi przypadło mi do gustu, o tyle z powodu ograniczeń w tworzeniu własnych adapterów muszę odpowiedni kod napisać sobie samodzielnie. Największą pomyłką w moim odczuciu było wykorzystanie standardowego mechanizmu sesji PHP, a wraz z nim zaimportowanie połowy jego wad.

W Zend_Session stworzenie własnego adaptera polega formalnie na stworzeniu nowej klasy implementującej odpowiedni interfejs, lecz zdefiniowane tam metody sesja podpina funkcją session_set_save_handler(). Już to samo z siebie narzuca sporo ograniczeń. Po pierwsze, standardowy mechanizm sesji oczekuje, że funkcja read() odczytująca zawartość sesji o podanym ID, zwróci zserializowaną tablicę. Analogicznie, zserializowana tablica przekazywana jest do wykonującej zapis funkcji write(). Programiści z pietruszki założyli, że wszyscy pragną przechowywać wszystkie dane w postaci jednego wielkiego ciągu tekstowego, co mija się z rzeczywistością. Po pierwsze, ktoś może chcieć w MySQL-u wykorzystać do składowania sesji tabelę typu MEMORY o rekordowo szybkim czasie dostępu, lecz niezezwalającą na tworzenie pól typu TEXT/BLOB. Krytyczne dane najlepiej jest więc przechowywać w oddzielnych, specjalnie wydzielonych polach, a co do pozostałych, należy sprawdzić, czy nie został przekroczony rozmiar pola VARCHAR (255 znaków), o ile w ogóle ktoś chce takie pole mieć - to też nie jest przesądzone. W końcu wiele aplikacji korzysta ze sztywnego schematu tabeli sesji o ustalonej liczbie pól.

Nawet, jeśli nie korzystamy z typu MEMORY, przeniesienie np. ID użytkownika w wydzielone pole umożliwi później tworzenie zapytań odpytujących, ilu mamy aktualnie zalogowanych użytkowników lub co robią. W oddzielnym polu można przechowywać informację, na jakiej podstronie internauta się znajduje, która będzie powiązana z rejestrem zasobów serwisu i pozwoli na precyzyjne wyświetlenie takich danych administratorowi jednym prostym zapytaniem. Zastosowań jest sporo.

Dla programisty najlepiej byłoby, gdyby dostawał tablicę danych i sam decydował o tym, które dane zapisać w postaci zserializowanej, które w dedykowanych miejscach, lub które da się odtworzyć automatycznie przy starcie sesji. Można zapytać: jejku, masz problem. Odserializuj sobie albo pobierz odpowiedni obiekt Zend_Session_Namespace i działaj, lecz czy to nie mija się z logiką? Jaki jest sens pakowania danych tylko, by je zaraz rozpakować i spakować ponownie, tylko już poprawnie? Nie ma żadnego, a na dodatek marnujemy czas na takie działania (ziarnko do ziarnka, a zbierze się miarka). Drugie rozwiązanie również budzi wątpliwości co do klarowności kodu. Skoro jest to wewnętrzny mechanizm sesji, nie powinniśmy z niego wyskakiwać i odwoływać się naokoło, zwłaszcza, że sesja na dokładkę dalej niepotrzebnie nam wszystko serializuje.

Gdyby klasa Zend_Session całkowicie zerwała z dokonaniami ekipy PHP sprzed ładnych paru lat, mogłaby z łatwością zorganizować pracę adapterów w znacznie lepszy sposób. Jedyna wada całkowicie nowego kodu, jaką dostrzegam, to konieczność ręcznego wywołania hipotetycznej metody save() pod koniec skryptu w celu zapisania zmian w sesji. Umieszczenie tego w destruktorze odpada - obiekt bazy danych może przecież zostać zniszczony przed sesją, a dodatkowo sam destruktor zachowuje się też dziwnie w stosunku do obsługi plików. Twórcy PHP odżegnują się od tego, zwalając całą winę na serwer Apache.

Powrót

Komentarze

Napisał Turgon w wtorek, 27 marca 2007 o 14:51

Zyx: Zepsuli, ale też apache nie jest bez winy. np. wykonanie CWD przed destruktorem i jaja są ;) . Z resztą sprawa życia obiektów, to po prostu masakra.

Napisał Bob w czwartek, 29 marca 2007 o 07:09

Z tym niszczeniem obiektów to twórcy php trochę przeginają. W 5.0 niszczone były w odwrotnej kolejności do inicjowania co oznaczało że mogliśmy do destruktora wrzucić zapisanie sesji. Od 5.1 nagle zachciało im się to zmienić i niszczone są w kolejności inicjowania co oznacza ręczne wywołanie jakiegoś $session->save. Mogliby się przynajmniej w ramach jednej wersji zdecydować na jedno rozwiązanie. Ktoś wie jak będzie w 6?

Napisał Zyx w czwartek, 29 marca 2007 o 13:10

Trzeba ściągnąć wersję alpha i zobaczyć, choć nie gwarantuje to wcale, że tak samo będzie w wersji finalnej :P. Ja destruktorów bez absolutnej konieczności po prostu nie używam, wolę sobie już sam zniszczyć obiekt. To jest jedyna rzecz skopana w "nowym" OOP.

Turgon -> Apache widocznie ma jakieś powody. Pytanie, czemu twórcy PHP umieścili wywołania destruktorów w takim miejscu :P.

Strona 1 z 1 :: 1

Skomentuj

NickInformacja
E-mailTylko do użytku wewnętrznego.
WWWNie zapomnij o http://
LayoutNapisz tu, czy widzisz dzienny czy nocny layout.
WpisFormatowanie wiki
Internauto, pamiętaj! Wolność to nie samowola - dbaj o kulturę wypowiedzi oraz dyskusji w sieci.

Na Zyxist.com panuje swoboda wyrażania opinii oraz krytyki pod dowolnym adresem. Jedyny warunek: musi być ona kulturalna i rzeczowa. Na chamstwo, prostactwo lub jawne obrażanie kogokolwiek nie ma tu miejsca i takie komentarze są bardzo szybko usuwane. Jeśli zamierzasz polemizować z treścią wpisu, wpierw uważnie ją przeczytaj.

© Tomasz "Zyx" Jędrzejewski 2005 - 2008 | Wykonanych zapytań: 2 | Serwer wirtualny zapewnia