Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<h1><ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[Zend_Session]]></ac:plain-text-body></ac:macro> Proposal Review</h1>

<ac:macro ac:name="info"><ac:parameter ac:name="title">Proposal Review Period</ac:parameter><ac:rich-text-body>
<p>This proposal is for review until <strong><ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><Unable to render embedded object: File (plain-text-body></ac:macro></strong>. This may change as the review progresses and more or less time is needed. You may enter comments directly at the end of the document, or for more directed comments you may <a><ac:plain-text-body><) not found.[CDATA[10010]]></ac:plain-text-body>">create a new issue</a> in the issue tracker for this project.</p></ac:rich-text-body></ac:macro>

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[]]></ac:plain-text-body></ac:macro>
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

]]></ac:plain-text-body></ac:macro>

<ac:macro ac:name="include"><ac:default-parameter>ZFDEV:Zend Proposal Zone Template</ac:default-parameter></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
session session Delete
proposal proposal Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jun 20, 2006

    <p>I generally like this proposal. There are two areas where I have initial comments: namespaces and transitory variables. It seems like namespaces were implemented just to allow transitory vars, and though I like both ideas I think their implementations should change to unlink them.</p>

    <p>It seems like the goal of transitory vars is to have them exist for some time shorter than the length of the session. Probably the three likely scenarios would be 1) a certain number of requests, 2) a certain time passing, 3) a certain event occurring/condition met. I would propose that any variable could have a transitory limit put on it and that the default was none (i.e. until the session expires).</p>

    <p>Without the need for namespaces for transitory vars I think the real need for namespaces is to separate the variables of different modules and applications. This would support interoperability. I would propose that when you get an instance of a session object that you can provide a name for the namespace that object will use. For example:</p>

    <p>     $session = Zend_Session::instance('Zend_Auth');<br />
         $session->set('is_signed_in', true);</p>

    <p>Would be conceptually equivalent to:</p>

    <p>     $_SESSION['Zend_Auth']['is_signed_in'] = true;</p>

    <p>This way a module, such as Zend_Auth, could operate with some security that its vars were not being trampled on.</p>

    <p>One last implementation idea that I have found handy is lazy session start. This is to get around the problem of headers being send in some conditions. To implement this, the call to session_start() is only done when the session vars are actually accessed, not at instantiation. This way the app can, for example, redirect early on an error even though the session object has previously been added to the registry. </p>

    1. Jun 20, 2006

      <p>Thanks..</p>

      <p>So yes, the namespace idea was to encourage encapsulation of data that belongs to some logical entity. There are 2 reasons for the _namespace functionality: </p>

      <p> First, to allow the user to extend Zend_Session while encouraging them to use the _namespace would also ensure they they dont overwrite data registered to zend_session via some other stream, like a plugin, etc. My current example is that I want to extend Zend_Session to be a Session handler (MyCompany_Session) that does a few things to check if the session is valid above and beyond the basic functionality... that being checking for a cookie set by our login server, etc..etc.. This way, before Zend_Session::_construct is run, I can run MyCompany_Session::_conststruct, store things i need inside a safe namespace, then forward to the Zend_Session::_construct.</p>

      <p> Secondly, these fucntions were suppose to be available to plugins, but through the design, these functions would have to be publicly defined.. So that is not what they are gonna be used for now.. As of now, a similar set of funcitons for saving to the session are in the Plugin_Abstract class and are available to use by plugins.</p>

      <p>So, this design should encourage other modules to link in with Zend_Session. Ideas I had were something like Zend_Message: auto registering with Zend_Session and allowing messages to be stored and retrieved by specific modules and/or controllers. Another idea is a User plugin that allows a user class to store and retrieve user information, doing things like regenerating a session id when the user's state changes. etc.</p>

      <p>Heh, I suppose that is alot. Let me know what you think.</p>

      <p>-ralph</p>

      1. Jun 20, 2006

        <p>I think we are really discussing different interfaces rather than functionality. I agree with the goal <em>"to allow the user to extend Zend_Session while encouraging them to use the _namespace would also ensure they they dont overwrite data registered to zend_session via some other stream, like a plugin, etc."</em> Perhaps the difference is that I would prefer an interface that encourages composition, whereas yours encourages inheritance.</p>

        <p>I also think the interface to installable session handlers and plugins should be separate, perhaps even passed to the constructor for easy initialization.</p>

        <p>I don't believe you addressed my comments on transitory values in the session. I am not sure this is even necessary, but if you implement it then fine grained control would probably be needs to meet the possible needs. </p>

        <p>Perhaps there should be a base session class that provides what is need following the 80/20 rule – and then other classes that extend the base class that provide greater functionality. </p>

        1. Jul 13, 2006

          <p>I have rethought out Zend_Session and took some of your comments into consideration in this newer verison.</p>

          <p>I think in this round the API takes care of the 80/20 rule completely. Usage can be as simple as</p>

          <p>$session = new Zend_Session();<br />
          $session->thing = "blah";</p>

          <p>// also isset($session->thing) || unset($session->thing)</p>

          <p>Also, I re-thought the transitory thing as well, and I agree that perhaps it is not nessissary in the Zend_Session class. Since most of the usage revolved around messaging, the idea is that messaging (and this idea of transitory variables) should be implemented in something like a Zend_Session_Messenger extension that would take care of those needs. Its late, hope I am explaining correctly. But this system does encourages composition over inheritance through this plugin model. When it comes down to it Zend_Session itself is a plugin implemenetation.</p>

  2. Jun 20, 2006

    <p>Since the default is to use the internal php functionality for sessions this is more a note for future implementation, for example on a DB.</p>

    <p>You should hash the session during the read and then check that hash during the write, If there have been no changes to the session there is no need to update the session, just the expire time.</p>

    <p>Since you use setters and such you could do that there, add a check variable that defaults to false and is changed to true when a setter is called.</p>

    <p>then on write if check variable is true write the whole session, otherwise just update the expire time.</p>

    1. Jun 20, 2006

      <p>Does PHP internally not take dirty-ness into consderation for sessions? I may run a few tests, I thought it did, but I also know that php-session code base is shaky at the moment. Some how between the version 4 and 5 split, patches got lost and were silently right before 5.1.3, I am not sure if they all made it back.</p>

      <p>In either case, if php does not check if the _SESSION has changed, I could include a public property isDirty that could be referenced before saving back to the database.. I assume that check would go into the writeClose funcitonality or in the destructor?</p>

      <p>-ralph</p>

      1. Jun 23, 2006

        <p>I know for a fact with custom session handlers write is called every page load and for good reason, even if the session has not changed you still need the chance to update the expiry time or your session would expire.</p>

      2. Jul 02, 2006

        <p>Just piping in that I can verify that the default behaviour for PHP sessions with files is to update the contents of the file for every page request, even when nothing has changed. There is no checking to make sure if the data has changed or not before saving.</p>

      3. Jul 17, 2006

        <p>Also you need to track the expire time..</p>

        <p>If no data has changed AND no more the X seconds have passed then don't waste database resources updating the expire time..</p>

        <p>Example, I expire sessions at 300 seconds, however I don't update the expire more then every 30 seconds if data hasn't been changed.</p>

        <p>This prevents in a enviroment where there are a lot of page loads by a single person constant updates that are not really needed.</p>

        1. Jul 18, 2006

          <p>Richard, is this something specific as to how one would implement the interface Zend_Session_SaveHandler_Interface?</p>

          <p>I havent used a database backend to sessions in quite a while as the filesystem and ram-disks have done great for me..</p>

          <p>I will look into writing a sample database interface to test though.</p>

      4. Jul 17, 2006

        <p>Last idea, You might want to have a static variable so you can track if a session has already been started. </p>

        <p>I use this to figure out if its a new session and if I need to write data to the table. It allowed me to cleanly track if the session already existed or not and prevent double inserts ( although I think the double inserts I was seeing are related to a bug in the session code )</p>

  3. Jun 21, 2006

    <p>Small notes:</p>

    <p>in Zend_Session_SaveHandler_Interface function write has id and data as unknown type, should be string I guess?<br />
    I also think we should support along with Zend_Session_SaveHandler_Interface the old way of setting handlers with functions - so that old code with handlers could be reused. Maybe with some class implementing this interface and accepting these handler functions in ctor. </p>

    <p>Also, it is not clear what is the role of Data Plugin interface - never mentioned in the proposal. </p>

  4. Jun 21, 2006

    <p>I was going to suggest the exact same namespacing syntax that Christopher described. <ac:emoticon ac:name="smile" /></p>

    <p>Are $session->foo and $session->get('foo') equivalent? (I assume they are.) It seems like get() and set() aren't necessary, since developers can use the simpler syntax, relying on __get() and __set(). In other words, instead of:</p>

    <p>$session->set('foo', 'bar');</p>

    <p>I can do:</p>

    <p>$session->foo = 'bar';</p>

    <p>This would let developers treat $session->foo exactly as they would $_SESSION<ac:link><ri:page ri:content-title="'foo'" /></ac:link>, making this class very intuitive. Combine that with namespaces, such that $session->foo can be used instead of $_SESSION<ac:link><ri:page ri:content-title="'namespace'" /></ac:link><ac:link><ri:page ri:content-title="'foo'" /></ac:link>, and you've got a pretty compelling reason to use Zend_Session.</p>

    <p>Do you have a description or example of the persistent login (remember me) feature?</p>

    1. Jun 21, 2006

      <blockquote><p>I was going to suggest the exact same namespacing syntax that Christopher described.</p></blockquote>
      <p>There's two votes. <ac:emoticon ac:name="smile" /></p>

      <blockquote><p>It seems like get() and set() aren't necessary.</p></blockquote>
      <p>PHP often make use of strings for names – so the get()/set() would be handy way to set things. I think ZF should be consistent across classes that use basic setters. Properties are fancy, but good old get()/set() are easy to override and make the implementation very clear.</p>

  5. Jun 23, 2006

    <p>On the general issue of accessing object properties, I would like to see Zend move toward some standardization of access to containers like a Session object. There are many objects that need this type of access and if they share a common container type then they can reuse lower-level functionality that supports that container type. </p>

  6. Jul 17, 2006

    <p>Hi Ralph - with the 0.4 proposal, how do you destroy or reset sessions? I can see there's a destroy() method for the storage container, but what about the plugin?</p>

    1. Jul 18, 2006

      <p>Simon,<br />
      It was my oversight to not have a destroy() method as part of the Core, that's fixed now.. But let me ask, given this flexible, multi-instanced implementation of sessions, how would you propose we handle session destruction?.. If one module, say Zend_Auth, is relying on a session.. should another module be able to destroy the entire session? As it stands, any module / plugin interface is allowed to do what it pleases with its own namespace.. ie: any session module can delete anything within its own namespace by calling $this->_session_core->namespaceUnset($this->_namespace); effectivly "resetting" itself.</p>

      <p>By having destroy() as part of the core, my thought process is that one single interface would have the responsiblity of destroying the session.. Perhaps its Zend_Auth or Zend_User particulary when a user logs out of a site.. That plugin interface would be responsible for issuing a $this->_session_core->destroy() call. Otherwise, it seems as though the common garbage collecting routines suffice in riding the application of old sessions.</p>

      <p>Another thought is to put a static method in Zend_Session, specifically Zend_Session::destroy(). By doing this, the user is aware that the destruction routine will affect all modules that depend on Zend_Session. </p>

      <p>What ya think?</p>

      1. Jul 18, 2006

        <p>I don't see any problem with destroying the instance itself. That would remove the temptation to 'sledgehammer' the session out of existence.</p>

        <p>So:-</p>

        <p>$session_auth = Zend_Session::getInstance('auth');<br />
        $session_form = Zend_Session::getInstance('form');</p>

        <p>$session_auth->id = 9999;<br />
        $session_form->hasSubmitted = true;</p>

        <p>$session_form->destroy();</p>

        <p>echo $session_form; // null</p>

        <p>But as to the whole session? Perhaps you could generate a hashed key, specifically for 'locking' or 'unlocking' the session. Once the key has been set (probably by the bootstrapper?) the session couldn't be destroyed unless you provide that key. So:-</p>

        <p>$key = Zend_Session::lock();</p>

        <p>Zend_Session::destroy(); // throws an exception<br />
        Zend_Session::lock(); // throws an exception because a key was already generated<br />
        Zend_Session::unlock($key) // ker-chink!<br />
        Zend_Session::destroy(); // OK - has been unlocked.</p>

        <p>The key obviously only survives on a per-request basis and is really only to prevent objects from stepping on each other's toes. You wouldn't register the key in the registry, for example, unless you wanted certain objects given the choice of taking control of the session.</p>

        <p>Just an idea - does it sound OK to you?</p>

  7. Jul 18, 2006

    <p>In my option this is more handy:</p>

    <h3>zend_session</h3>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    class zend_session extends zend_session_plugin_abstract
    {
    /**

    • Description.
      *
    • @var array
      */
      static private $_defaultOptions = array();

    /**

    • Description.
      *
    • @var boolean
      */
      static private $_optionsParsed = false;

    /**

    • Description.
      *
    • @var array
      */
      static private $_instances = array();

    /**

    • Description.
      *
    • @param array $userOptions
    • @return void
      */
      static public function setOptions(array $userOptions);

    /**

    • Description.
      *
    • @param kernel_session_handler_interface $handler
    • @return void
      */
      static public function setSaveHandler(zend_session_handler_interface $handler);

    /**

    /**

    /**

    /**

    /**

    /**

    /**

    • Description.
      *
    • @param mixed $name
    • @return object
      */
      static public function getInstance($name = 'default');

    /**

    • Constructor.
      *
    • @param string $namespace
    • @return void
      */
      public function __construct($namespace);
      }
      ]]></ac:plain-text-body></ac:macro>

    <h3>zend_session_plugin_abstract</h3>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    abstract class zend_session_plugin_abstract
    {
    /**

    • Description.
      *
    • @var string
      */
      protected $_namespace;

    /**

    • Constructor.
      *
    • @return void
      */
      public function __construct();

    /**

    • Get the current namespace.
      *
    • @return string
      */
      public function __toString();

    /**

    • Description.
      *
    • @return boolean
      */
      public function __isset($name);

    /**

    • Description.
      *
    • @return void
      */
      public function __set($name, $value);

    /**

    • Description.
      *
    • @return mixed
      */
      public function __get($name);

    /**

    • Description.
      *
    • @return void
      */
      public function __unset($name);

    /**

    • Clear the current namespace.
      *
    • @return void
      */
      public function clear();
      }
      ]]></ac:plain-text-body></ac:macro>

    <h3><span style="text-decoration: line-through;">Zend_Session_Core</span></h3>

    <p>I can not say anymore because my english is really bad. I'm sorry for that!</p>

    <p>Greetings from germany,<br />
    Daniel</p>

    1. Jul 18, 2006

      <h3>Small update for zend_session:</h3>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      /**

      • Description.
        *
      • @see http://php.net/session_destroy/
      • @param zend_session_plugin_abstract $name
      • @return void
        */
        static public function destroy(zend_session_plugin_abstract $name = null)
        Unknown macro: { if (!is_null($name))
        Unknown macro: { $namespace = $name->__toString(); unset($_SESSION[$namespace]); }
        else
        Unknown macro: { $_SESSION = array(); session_destroy(); }
        }

        ]]></ac:plain-text-body></ac:macro>

      <h3>Use Case:</h3>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      zend_session::start();

      $session_auth = zend_session::getInstance('auth');
      $session_user = zend_session::getInstance(new zend_session_plugin_user());

      zend_session::destroy($session_user);
      zend_session::destroy();
      ]]></ac:plain-text-body></ac:macro>

  8. Oct 26, 2006

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Feedback</ac:parameter><ac:rich-text-body><p>Conditionally accepted with the following changes required:</p>

    <p>#1 Clean, clear separation of Zend_Session and Zend_Session_Core APIs. The former should contain only methods to manipulate namespaced session data, while the latter should contain only methods to manipulate global session attributes, behaviors, and provide Zend_Session instances access to namespaced session data.</p>

    <p>#2 Zend_Session_Core should provide public access to the session "bootstrap, such that a developer can invoke the session bootstrap from with their ZF bootstrap code, or selectively within individual actions, if they wish to only incur session startup overhead for specific situations.</p>

    <p>#3 Session validation has many forms. As with most security related process, there are many balance points with many trade-offs. Thus, each developer of a ZF app must choose session validation techniques that meet their needs. Session validator plugins will provide this flexibility. The first version of Zend_Session in the incubator should provide a mechanism for dynamically registering session validator plugins with Zend_Session_Core, whether as a one-time-only validation, or as a sticky validator for all further requests from the same session. </p>

    <p>After Zend_Session enters the incubator and receives substantial testing form the community, based on community feedback, and practical use cases, the session validation mechanism may or may not be expanded, subject to the normal review process for significant additions to components.</p></ac:rich-text-body></ac:macro>

  9. Apr 04, 2007

    <p>Hello,</p>

    <p>I already wrote this in the proposal area for Registry, but this also belongs to this area.</p>

    <p>In my opionion Registry objects and session objects should not be treated completely differently. Actually they should implement the same interface, because the have similar tasks, which is storing objects.</p>

    <p>At the moment I hate it to access session objects and registry objects in different ways. Secondary these objects are not exchangeable because of the lack of an standardised interface.</p>

    <p>In my opinion a session object is nothing more than a registry object which stores the data longer.</p>

    <p>Additionally there should even exist a registry object that persists data longer than a session by writing data on the harddisk.</p>

    <p>And there should be the observer pattern implemented, allowing objects to get informed when new entries are added, deleted or changed.</p>

    <p>So a session class should not be implemented without working together with the programmers of the registry class and registry classes and the session classed shouldn't be treated seperately.</p>