Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve constructor injection of Zend\Session?

The architecture of the Session component in Zend Framework 2 is yet undocumented and I'm having some trouble understanding it's practical use (compared to the very intuitive Symfony Session for example).

A short summary of the important pieces:

  • Zend\Session\Storage\SessionStorage maps and replaces the $_SESSION superglobal
  • Zend\Session\SessionManager is a facade to manage the storage, the session cookies, session configuration, session validation, etc.
  • Zend\Session\Container is a sort of replacement for the old Session_Namespace, different Containers share one Manager instance (via a static field).

There is no component that represents a collection of namespaces (containers) and therefore there is no way of using methods like 'issetNamespaceX', 'unsetNamespaceX', etc. Nobody (including the Manager as well as Storage) knows about the containers, whether there are any, and if, how many with what names.

Matthew Weier O'Phinney explained this circumstance as follows:

The Container is a special class for working with isolated segments of the current Storage instance. [...] If anything, a Storage adapter would contain Containers, not the Manager. However, we also want to allow more basic usage of storage, which makes the Container orthogonal to Storage, and which explains the difference in has-a relations.

I see a couple of practical problems with this solution with regard to proper dependency injection. Obviously the Manager can be seen as a service with a rather long lifetime and therefore qualifies for constructor injection. Unfortunately, the Manager has no clue about the Containers which forces me to either inject Containers as well (bad because rather short lived and takes slots away), write my own additional functionality to make the Storage or the Manager Container-aware (should be framework functionality) or create Containers in my Consuming classes (which I want to avoid obviously).

So the Zend solution doesn't seem practical to me. If I want to use the Manager, the FlashMessenger and an additional container, I need to inject 4 (four!) classes. If I do the same with the Symfony Session, I only need to inject 1 (one) class.

Furthermore Containers don't qualify for injection since they're potentially short lived run time objects, which may exist or may not at a given point during script execution. With Symfony Session this is not a problem since the Session is aware of it's bags (containers), with ZF2 this is a problem since the Manager is NOT aware of the Containers.


Main question: How am I supposed to use Zend\Session with Containers in practice?

Additional question: Is there a good reason not to provide real namespace functionality similar to ZF1 or for example similar to the Symfony SessionBag?

like image 210
markus Avatar asked Dec 16 '12 19:12

markus


1 Answers

I'm not 100% certain I understand what issues you're getting at.

First, the constructor for a Container accepts both the namespace for the container, as well as optionally the Manager instance: $container = new Container('your container namespace here', $manager). You can specify a default manager instance to use as well: Container::setDefaultManager($manager).

Second, a Container represents simply a named array within the Storage instance used. As such, you can test for existence of a container by doing an isset($storage['your container namespace here']) call.

What exact issues are you running up against that the above do not solve? From your description, it sounds like (a) you were not aware that containers have a 1:1 relationship with the storage, and (b) that you can inject a manager into the container instances. If there are additional problems, I'd like to better understand them.

like image 176
weierophinney Avatar answered Sep 21 '22 22:09

weierophinney