<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="learning.multiuser.sessions">
    <title>Managing User Sessions In ZF</title>

    <sect2 id="learning.multiuser.sessions.intro">
        <title>Introduction to Sessions</title>

        <para>
            The success of the web is deeply rooted in the protocol that drives the web:
            <acronym>HTTP</acronym>. <acronym>HTTP</acronym> over TCP is by its very nature
            stateless, which means that inherently the web is also stateless. While this very aspect
            is one of the dominating factors for why the web has become such a popular medium, it
            also causes an interesting problem for developers that want to use the web as an
            application platform.
        </para>

        <para>
            The act of interacting with a web application is typically defined by the sum
            of all requests sent to a web server. Since there can be many consumers being served
            simultaneously, the application must decide which requests belong to which consumer.
            These requests are typically known as a "session".
        </para>

        <para>
            In <acronym>PHP</acronym>, the session problem is solved by the session extension which
            utilizes some state tracking, typically cookies, and some form of local storage which is
            exposed via the $_SESSION superglobal. In Zend Framework, the component
            <classname>Zend_Session</classname> adds value to the <acronym>PHP</acronym> session
            extension making it easier to use and depend on inside object-oriented applications.
        </para>
    </sect2>

    <sect2 id="learning.multiuser.sessions.basic-usage">
        <title>Basic Usage of Zend_Session</title>

        <para>
            The <classname>Zend_Session</classname> component is both a session manager as well as
            an <acronym>API</acronym> for storing data into a session object for long-term
            persistence. The <classname>Zend_Session</classname> <acronym>API</acronym> is for
            managing the options and behavior of a session, like options, starting and stopping a
            session, whereas <classname>Zend_Session_Namespace</classname> is the actual object used
            to store data.
        </para>

        <para>
            While its generally good practice to start a session inside a bootstrap process, this
            is generally not necessary as all sessions will be automatically started upon the first
            creation of a <classname>Zend_Session_Namespace</classname> object.
        </para>

        <para>
            <classname>Zend_Application</classname> is capable of configuring
            <classname>Zend_Session</classname> for you as part of the
            <classname>Zend_Application_Resource</classname> system. To use this, assuming your
            project uses <classname>Zend_Application</classname> to bootstrap, you would add the
            following code to your application.ini file:
        </para>

        <programlisting language="php"><![CDATA[
resources.session.save_path = APPLICATION_PATH "/../data/session"
resources.session.use_only_cookies = true
resources.session.remember_me_seconds = 864000
]]></programlisting>

        <para>
            As you can see, the options passed in are the same options that you'd expect to find
            in the ext/session extension in <acronym>PHP</acronym>. Those options setup the path
            to the session files where data will be stored within the project. Since
            <acronym>INI</acronym> files can additionally use constants, the above will use the
            APPLICATION_PATH constant and relatively point to a data session directory.
        </para>

        <para>
            Most Zend Framework components that use sessions need nothing more to use
            <classname>Zend_Session</classname>. At this point, you an either use a component that
            consumes <classname>Zend_Session</classname>, or start storing your own data inside a
            session with <classname>Zend_Session_Namespace</classname>.
        </para>

        <para>
            <classname>Zend_Session_Namespace</classname> is a simple class that proxies data via an
            easy to use <acronym>API</acronym> into the <classname>Zend_Session</classname> managed
            $_SESSION superglobal. The reason it is called
            <classname>Zend_Session_Namespace</classname> is that it effectively namespaces the data
            inside $_SESSION, thus allowing multiple components and objects to safely store and
            retrieve data. In the following code, we'll explore how to build a simple session
            incrementing counter, starting at 1000 and resetting itself after 1999.
        </para>

        <programlisting language="php"><![CDATA[
$mysession = new Zend_Session_Namespace('mysession');

if (!isset($mysession->counter)) {
    $mysession->counter = 1000;
} else {
    $mysession->counter++;
}

if ($mysession->counter > 1999) {
    unset($mysession->counter);
}
]]></programlisting>

        <para>
            As you can see above, the session namespace object uses the magic __get, __set,
            __isset, and __unset to allow you to seamlessly and fluently interact with the session.
            The information stored in the above example is stored at
            $_SESSION['mysession']['counter'].
        </para>
    </sect2>

    <sect2 id="learning.multiuser.sessions.advanced-usage">
        <title>Advanced Usage of Zend_Session</title>

        <para>
            Additionally, if you wanted to use the DbTable
            save handler for <classname>Zend_Session</classname>, you'd add the following code to
            your application.ini:
        </para>

        <programlisting language="php"><![CDATA[
resources.session.saveHandler.class = "Zend_Session_SaveHandler_DbTable"
resources.session.saveHandler.options.name = "session"
resources.session.saveHandler.options.primary.session_id = "session_id"
resources.session.saveHandler.options.primary.save_path = "save_path"
resources.session.saveHandler.options.primary.name = "name"
resources.session.saveHandler.options.primaryAssignment.sessionId = "sessionId"
resources.session.saveHandler.options.primaryAssignment.sessionSavePath = "sessionSavePath"
resources.session.saveHandler.options.primaryAssignment.sessionName = "sessionName"
resources.session.saveHandler.options.modifiedColumn = "modified"
resources.session.saveHandler.options.dataColumn = "session_data"
resources.session.saveHandler.options.lifetimeColumn = "lifetime"
]]></programlisting>
    </sect2>
</sect1>
