Image for Sesje w Zend Framework 2

Sesje w Zend Framework 2

Czas czytania:

Dlaczego stosować sesje

Zbudowanie profesjonalnej aplikacji bez wykorzystania sesji jest praktycznie niemożliwe. Jako że protokół HTTP jest bezstanowy, serwer WWW musi mieć możliwość zidentyfikowania powracającego użytkownika aby zaserwować mu odpowiednie dane. Sesje służą więc do identyfikacji użytkowników i składowania danych. Działanie ich jest bardzo proste. Serwer tworzy unikalny identyfikator za pomocą którego jest identyfikowany na serwerze plik (zbiór) danych dotyczący danego użytkownika. Ten sam identyfikator jest zostawiany u klienta (np. za pomocą cookies) i w momencie przyjścia żądania na serwer sprawdzany jest ten identyfikator i porównywany z zasobami serwera. Dzięki temu serwer wie, który użytkownik wysłał żądanie.

Standardowe korzystanie z sesji w ZF2

Główną klasa odpowiedzialną za obsługę/zarządzanie sesji w ZF2 jest ZendSessionSessionManager. Zajmuje się ona inicjalizacją sesji, jej konfiguracją, zapisem danych do sesji oraz jej zniszczeniem. Na początku należy dokonać konfiguracji sesji w pliku konfiguracyjnym a następnie należy zainicjować sesję. Można to zrobić w pliku Module.php Standardowa obsługa wygląda następująco:

public function bootstrapSession( $e ) {
	$session = $e->getApplication()->getServiceManager()->get( 'ZendSessionSessionManager' );
	$session->start();
	$container = new Container( 'initialized' );
	if ( ! isset( $container->init ) ) {
		$serviceManager = $e->getApplication()->getServiceManager();
		$request        = $serviceManager->get( 'Request' );
		$session->regenerateId( true );
		$container->init          = 1;
		$container->remoteAddr    = $request->getServer()->get( 'REMOTE_ADDR' );
		$container->httpUserAgent = $request->getServer()->get( 'HTTP_USER_AGENT' );
		$config                   = $serviceManager->get( 'Config' );
		if ( ! isset( $config['session'] ) ) {
			return;
		}
		$sessionConfig = $config['session'];
		if ( isset( $sessionConfig['validators'] ) ) {
			$chain = $session->getValidatorChain();
			foreach ( $sessionConfig['validators'] as $validator ) {
				switch ( $validator ) {
					case 'ZendSessionValidatorHttpUserAgent':
						$validator = new $validator( $container->httpUserAgent );
						break;
					case 'ZendSessionValidatorRemoteAddr':
						$validator = new $validator( $container->remoteAddr );
						break;
					default:
						$validator = new $validator();
				}
				$chain->attach( 'session.validate', array( $validator, 'isValid' ) );
			}
		}
	}
}

public function getServiceConfig() {
	return array(
		'factories' => array(
			'ZendSessionSessionManager' => function ( $sm ) {
				$config = $sm->get( 'config' );
				if ( isset( $config['session'] ) ) {
					$session       = $config['session'];
					$sessionConfig = null;
					if ( isset( $session['config'] ) ) {
						$class         = isset( $session['config']['class'] ) ? $session['config']['class'] : 'ZendSessionConfigSessionConfig';
						$options       = isset( $session['config']['options'] ) ? $session['config']['options'] : array();
						$sessionConfig = new $class();
						$sessionConfig->setOptions( $options );
					}
					$sessionStorage = null;
					if ( isset( $session['storage'] ) ) {
						$class          = $session['storage'];
						$sessionStorage = new $class();
					}
					$sessionSaveHandler = null;
					$sessionManager     = new SessionManager( $sessionConfig, $sessionStorage, $sessionSaveHandler );
				} else {
					$sessionManager = new SessionManager();
				}
				Container::setDefaultManager( $sessionManager );

				return $sessionManager;
			},
		),
	);
}

I na sam koniec w metodzie onBootstrap() wywołujemy utworzoną wcześniej metodę: $this->bootstrapSession($e); W ten sposób możemy używać standardowej sesji w następujący sposób np:

$session = new Container('myContainer'); 
$session->foo = 'test'; 
echo $session->foo;

Alternatywne sposoby obsługi sesji

Nie zawsze najbardziej optymalne wydaje się standardowe wykorzystanie sesji. Czasami specyfika aplikacji, architektura, wydajność powodują że standardowe podejście nie wystarcza. W takiej sytuacji można skorzystać z innych technologi obsługi sesji. W przypadku gdy aplikacja ma strukturę rozproszoną niemożliwe jest wykorzystanie sesji na plikach. W takiej sytuacji najlepiej skorzystać z obsługi przy pomocy bazy danych. Dokonać tego można w prosty sposób. Należy utworzyć odpowiednią tabelę w bazie np. za pomocą poniższego polecenia :

CREATE TABLE `my_sessions` (     `id` char(32),     `name` char(32),     `modified` int,     `lifetime` int,     `data` text,     PRIMARY KEY (`id`, `name`) );

Wystarczy odpowiednio zmodyfikować plik konfiguracyjny aby dołożyć obsługę bazy danych:

return array( ...     'db'      => array(
	'driver'   => 'Mysqli',
	'host'     => 'localhost',
	'dbname'   => 'test',
	'username' => 'root',
	'password' => 'mysql',
	'options'  => array( 'buffer_results' => true )
),
              'service_manager' => array( 'factories' => array( 'ZendDbAdapterAdapter' => 'ZendDbAdapterAdapterServiceFactory', ), ),
...
);

a następnie w metodzie getServiceConfig odpowiednio ustawić zmienną $sessionSaveHandler:

$adapter = new ZendDbAdapterAdapter($config['db']); 
$tableGateway = new TableGateway('my_sessions', $adapter); 
$sessionSaveHandler = new DbTableGateway($tableGateway, new DbTableGatewayOptions());

pamiętając o dołożeniu odpowiednich deklaracji:

use ZendDbTableGatewayTableGateway; 
use ZendSessionSaveHandlerDbTableGateway; 
use ZendSessionSaveHandlerDbTableGatewayOptions; 
use ZendSessionSessionManager;

W tym momencie obsługa sesji zostaje przeniesiona do bazy danych. Niestety obsługa sesji na bazie danych może nie wystarczyć. Duże obciążenie aplikacji generowane poprzez ruch na stronie może spowodować wąskie gardło dla tak rozwiązanej sesji. Ratunkiem w tej sytuacji jest skorzytanie z memcache, który jest bardziej wydajny przy analogicznych wymaganiach sprzętowych a umożliwia pracę także w środowisku rozproszonym. Zastosowanie memacache nie powoduje dużych zmian w naszej aplikacji. Wystarczy zmodyfikować zmienną $sessionSaveHandler

use ZendCacheStorageFactory; 
use ZendSessionSaveHandlerCache;  
$cache = StorageFactory::factory($config); 
$sessionSaveHandler = new Cache($cache);

gdzie $config to tablica postaci:

array(
	'adapter' => array(
		'name'     => 'memcached',
		'lifetime' => 7200,
		'options'  => array(
			'servers'   => array( array( '127.0.0.1', 11211 ) ),
			'namespace' => 'myNamespace',
		),
	)
)

którą można sobie umieścić w pliku konfiguracyjnym, dzięki czemu modyfikacja parametrów będzie bardzo prosta. Poza przedstawionymi powyżej przykładami rozwiązań obsługi sesji można skorzystać także z innych bardziej zaawansowanych i mniej znanych rozwiązań. Alternatywnym sposobem korzytania z sesji jest wykorzystanie innych nierelacyjnych baz danych np MongoDb. Podobnie jak w przypadku powyższych rozwiązań konfiguracja nie jest trudna.

use Mongo; 
use ZendSessionSaveHandlerMongoDB; 
use ZendSessionSaveHandlerMongoDBOptions; 
use ZendSessionSessionManager;  
$mongo = new Mongo(); 
$options = new MongoDBOptions(array(     'database' => 'mydb',     'collection' => 'sessions', )); 
$sessionSaveHandler = new MongoDB($mongo, $options);

Zainteresował Cię ten artykuł?

Oferujemy profesjonalne wsparcie programistów w technologii Web.
Może Cię również zainteresować:
5 rzeczy, na które warto zwrócić uwagę, wybierając dedykowany system klasy ERP, WMS lub LMS

Tworzenie dedykowanych aplikacji web’owych (dostępnych przez przeglądarkę WWW z poziomu komputera, tabletu czy telefonu) jest… Read More

Clutch Recognizes GOGOmedia as a 2022 Development Leader in Poland

GOGOmedia is a multidisciplinary team with vast experience in the digital technology space. We deliver… Read More