title: Zend Navigation: Where should I load the ACL 'Role' in a private application
body: <p>I am working on a 'private' application, you must be logged in to do anything at all. This gives me a bit of a an issue loading the role for Zend Navigation. Currently I am 'init'ing Zend Navigation in my bootstrap; that was fine until I added ACL to Zend Nav. The issue is that I want to load the 'userRole' from my auth storage, but there will not be storage yet until the user logs in, so that gets me a 'Trying to get property of non-object' warning at the login page. This is because before login, there is nothing in auth's storage, so <code>auth-&gt;userRole</code> is 'nothing' because <code>auth-&gt;getInstance()-&gt;getIdentity()-&gt;???</code> would be empty, until a user logs in and the auth is configured.</p>
  
  <p>I'm not using Zend Nav at the login page, in fact I have an alternate layout for the login page (no nav at all); <code>'if !$auth-&gt;hasIdentity'</code> (false) use the login layout, only show the login page for that matter system-wide, as I said the application is completely private so defaulting to a 'guest' role or something like that seems like a 'dirty' approach, because once a user logs in it will have to reconfigure auth anyhow. It just don't seem right to set a generic auth identity just to please the login page.</p>
  
  <p>What I am getting at is, where is a good place to move the 'init' of Zend Nav, or at least move the configure ACL part? May as well move the whole thing?</p>
  
  <p>This is what I have in my bootstrap.php for Zend Navigation:</p>
  
  <pre><code>protected function _initNavigation() {
      $this-&gt;_logger-&gt;info('Bootstrap ' . __METHOD__);
  
      $this-&gt;bootstrap('layout');
      $layout = $this-&gt;getResource('layout');
      $view = $layout-&gt;getView();
      $config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
      $container = new Zend_Navigation($config);
      $acl = new Application_Model_Acl_Acl();
      $role = Zend_Auth::getInstance()-&gt;getIdentity()-&gt;userRole;
      $view-&gt;navigation($container)-&gt;setAcl($acl)-&gt;setRole($role);
  }
  </code></pre>
  
  <p>It is the <code>'$role = Zend_Auth::getInstance()-&gt;getIdentity()-&gt;userRole'</code> that is empty (or a non-object) at the time bootstrap runs.</p>
  
  <p>All of my ACL takes place either in the controller (at the action) or some may take place in the models at some point, although I don't anticicpate web service or anything, so maybe they will stay in the controller, but I have the flexibility because I have the ACL in the models (that would be the 'domain' right?</p>
  
  <p>I am only using ACL on Zend Nav for layout, user experience purposes; The menu and links I get from Zend Nav will be 'greyed', non-existant, or active (and visible) according to the user role, for example a 'user' role will not get many 'admin' options, and this is re-enforced by ACL in the controller so one could not simply type the url and get to an area either.</p>
  
  <p>My other thought was that maybe I should be thinking of moving my login into the bootstrap for this situation, but I'm not sure that is a good idea either?</p>
  
  <hr>
  
  <p><strong>EDIT:</strong>
  This is the code that I put into a Front Controller Plugin:</p>
  
  <pre><code>class Plugins_Controller_ZendNavInit extends Zend_Controller_Plugin_Abstract {
  
          public function preDispatch(Zend_Controller_Request_Abstract $request) {
  
              $auth = Zend_Auth::getInstance();
  
              if ($auth-&gt;hasIdentity()) {
  
                  $config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
                  $container = new Zend_Navigation($config);
                  $acl = new Application_Model_Acl_Acl();
  
                  $layout = Zend_Layout::getMvcInstance();
                  $view = $layout-&gt;getView();
  
                  $role = Zend_Auth::getInstance()-&gt;getIdentity()-&gt;userRole;
                  $view-&gt;navigation($container)-&gt;setAcl($acl)-&gt;setRole($role);
              }
          }
      }
  </code></pre>
  
  <p>Works great; I of course, had to register my plugin just like any other. I also moved my Auth checking to a front-controller plugin too.</p>