@@ -378,5 +378,230 @@ abstracts the hard work behind a simple API::
378378Session
379379-------
380380
381- TBD -- This part has not been written yet as it will probably be refactored
382- soon in Symfony 2.1.
381+ The Symfony2 HttpFoundation Component has a very powerful and flexible session
382+ subsystem which is designed to provide session management through a simple
383+ object-oriented interface using a variety of session storage drivers.
384+
385+ Quick example:
386+
387+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Session;
388+
389+ $session = new Session();
390+ $session->start();
391+
392+ // set and get session attributes
393+ $session->set('name', 'Drak');
394+ $session->get('name');
395+
396+ // set and retrieve flash messages
397+ $session->getFlashBag()->set('notice', 'Profile updated');
398+
399+ echo $session->getFlashBag()->get('notice');
400+
401+ Save Handlers
402+ ~~~~~~~~~~~~~
403+
404+ The PHP session workflow has 6 possible operations that may occur. The normal
405+ session follows `open `, `read `, `write ` and `close `, with the possibility of
406+ `destroy ` and `gc ` (garbage collection which will expire any old sessions: `gc `
407+ is called randomly according to PHP's configuration and if called, it is invoked
408+ after the `open ` operation). You can read more about this at
409+ http://php.net/session.customhandler
410+
411+ Native PHP Save Handlers
412+ ~~~~~~~~~~~~~~~~~~~~~~~~
413+
414+ So-called 'native' handlers are session handlers are either compiled into PHP or
415+ provided by PHP extensions, such as PHP-Sqlite, PHP-Memcached and so on. The
416+ handlers are compiled and can be activated directly in PHP using
417+ `ini_set('session.save_handler', $name); ` and are usually configured with
418+ `ini_set('session.save_path', $path); ` and sometimes, a variety of other PHP
419+ `ini ` directives.
420+
421+ Symfony2 provides drivers for native handlers which are easy to configure, these are:
422+
423+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler `
424+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeSqliteSessionHandler `
425+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeMemcacheSessionHandler `
426+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeMemcachedSessionHandler `
427+
428+ Example of use:
429+
430+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Session;
431+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Storage\\ NativeSessionStorage;
432+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Storage\\ Handler\\ NativeMemcachedSessionHandler;
433+
434+ $storage = new NativeSessionStorage(array(), new NativeMemcachedSessionHandler());
435+ $session = new Session($storage);
436+
437+ Custom Save Handlers
438+ ~~~~~~~~~~~~~~~~~~~~
439+
440+ Custom handlers are those which completely replace PHP's built in session save
441+ handlers by providing six callback functions which PHP calls internally at
442+ various points in the session workflow.
443+
444+ Symfony2 HttpFoudation provides some by default and these can easily serve as
445+ examples if you wish to write your own.
446+
447+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler `
448+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcacheSessionHandler `
449+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler `
450+ * `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler `
451+
452+ Example:
453+
454+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Session;
455+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Storage\\ SessionStorage;
456+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Storage\\ Handler\\ PdoSessionHandler;
457+
458+ $storage = new NativeSessionStorage(array(), new PdoSessionHandler());
459+ $session = new Session($storage);
460+
461+ Session Bags
462+ ------------
463+
464+ PHP's session management requires the use of the `$_SESSION ` super-global,
465+ however, this interferes somewhat with code testability and encapsulation in a
466+ OOP paradigm. To help overcome this Symfony2 uses 'session bags' linked to the
467+ session to encapsulate a specific dataset like 'attributes' or 'flash messages'.
468+
469+ This approach also mitigates namespace pollution within the `$_SESSION `
470+ super-global because each bag stores all it's data under a unique namespace.
471+ This allows Symfony2 to peacefully co-exist with other applications or libraries
472+ that might use the `$_SESSION ` super-global and all data remains completely
473+ compatible with Symfony2's session management.
474+
475+ Symfony2 provides 2 kinds of bags, with two separate implementations.
476+ Everything is written against interfaces so you may extend or create your own
477+ bag types if necessary.
478+
479+ Attributes
480+ ~~~~~~~~~~
481+
482+ The purpose of the bags implementing the `AttributeBagInterface ` is to handle
483+ session attribute storage. This might include things like user ID, and remember
484+ me login settings or other user based state information.
485+
486+ * `AttributeBag ` - this is the standard default implementation.
487+ * `NamespacedAttributeBag ` - this implementation allows for attributes to be
488+ stored in a structured namespace.
489+
490+ Any plain `key => value ` storage system is limited in the extent to which
491+ complex data can be stored since each key must be unique. You can achieve
492+ namespacing by introducing a naming convention to the keys so different parts of
493+ your application could operate without clashing. For example, `module1.foo ` and
494+ `module2.foo `. However, sometimes this is not very practical when the attributes
495+ data is an array, for example a set of tokens. In this case, managing the array
496+ becomes a burden because you have to retrieve the array then process it and
497+ store it again.
498+
499+ 'tokens' => array('a' => 'a6c1e0b6',
500+ 'b' => 'f4a7b1f3')
501+
502+ So any processing of this might quickly get ugly, even simply adding a token to
503+ the array:
504+
505+ $tokens = $session->get('tokens');
506+ $tokens['c'] = $value;
507+ $session->set('tokens', $tokens);
508+
509+ With structured namespacing, the the key can be translated to the array
510+ structure like this using a namespace character (defaults to `/ `).
511+
512+ $session->set('tokens/c', $value);
513+
514+ This way you can easily access a key within the stored array directly and easily.
515+
516+ Flash messages
517+ ~~~~~~~~~~~~~~
518+
519+ The purpose of the `FlashBagInterface ` is to provide a way of settings and
520+ retrieving messages on a per session basis. The usual workflow for flash
521+ messages would be set in an request, and displayed on page redirect. For
522+ example, a user submits a form which hits an update controller, and after
523+ processing the controller redirects the page to either the updated page or a
524+ error page. Flash messages set in the previous page request would be displayed
525+ immediately on the subsequent page load for that session. This is however just
526+ one application for flash messages.
527+
528+ * `AutoExpireFlashBag ` - This implementation messages set in one page-load will
529+ be available for display only on the next page load. These messages will auto
530+ expire regardless of if they are retrieved or not.
531+ * `FlashBag ` - In this implementation, messages will remain in the session until
532+ they are explicitly retrieved or cleared. This makes it possible to use ESI
533+ caching.
534+
535+ Testability
536+ -----------
537+
538+ Symfony2 is designed from the ground up with code-testability in mind. In order
539+ to make your code which utilises session easily testable we provide two separate
540+ mock storage mechanisms for both unit testing and functional testing.
541+
542+ Testing code using real sessions is trick because PHP's workflow state is global
543+ and it is not possible to have multiple concurrent sessions in the same PHP
544+ process.
545+
546+ The mock storage engines simulate the PHP session workflow without actually
547+ starting one allowing you to test your code without complications. You may also
548+ run multiple instances in the same PHP process.
549+
550+ The only caveat, `session_id() ` is global, so the session ID should be read
551+ using `$session->getId() ` but generally this is of no relevance during testing.
552+
553+ Unit Testing
554+ ~~~~~~~~~~~~
555+
556+ For unit testing where it is not necessary to persist the session, you should
557+ simply swap out the default storage engine with
558+ `Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage `.
559+
560+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Storage\\ MockArraySessionStorage;
561+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Session;
562+
563+ $session = new Session(new MockArraySessionStorage());
564+
565+ Functional Testing
566+ ~~~~~~~~~~~~~~~~~~
567+
568+ For functional testing where you may need to persist session data across
569+ separate PHP processes, simply change the storage engine to
570+ `Symfony\\Component\\HttpFoundation\\SessionMockFileSessionStorage `.
571+
572+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Session;
573+ use Symfony\\ Component\\ HttpFoundation\\ Session\\ Storage\\ MockFileessionStorage;
574+
575+ $session = new Session(new MockFileSessionStorage());
576+
577+ PHP 5.4 compatibility
578+ ~~~~~~~~~~~~~~~~~~~~~
579+
580+ Since PHP 5.4.0, `\SessionHandler ` and `\SessionHandlerInterface ` are available.
581+ Symfony 2.1 provides forward compatibility for the `\SessionHandlerInterface ` so
582+ it can be used under PHP 5.3. This greatly improves inter-operability with other
583+ libraries.
584+
585+ `\SessionHandler ` is a special PHP internal class which exposes native save
586+ handlers to PHP user-space. You can read more about it at
587+ http://php.net/sessionhandler.
588+
589+ In order to provide a solution for those using PHP 5.4, Symfony2 has a special
590+ class called `Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeSessionHandler `
591+ which under PHP 5.4, extends from `\SessionHandler ` and under PHP 5.3 is just a
592+ empty base class. This provides some interesting opportunities to leverage
593+ PHP 5.4 functionality if it is available.
594+
595+ Handler Proxy
596+ ~~~~~~~~~~~~~
597+
598+ `SessionStorage ` injects storage handlers into a handler proxy. The reason for
599+ this is that under PHP 5.4, all handlers implement `\SessionHandlerInterface `
600+ including native handlers (those which activate internal PHP/PHP-extension
601+ handlers. Native handlers under PHP 5.4 will be children of
602+ `\SessionHandler ` which allows one to intercept and modify even native session
603+ handlers.
604+
605+ In order to manage all of this, Symfony2 uses a proxy handler object. It means
606+ that you could write a single adapter, that for example encrypts the session
607+ data, and it will work regardless of the save handler in use, custom, or native.
0 commit comments