I have a sidebar which appears on every page. The first elements of the sidebar are either a) a login form, or b) details of the current user, (depending on whether the user is logged in or not).
I have read up on a few ways to accomplish this and am planning to initialise a sidebar placeholder in the bootstrap.
When it comes to appending the user details, or the login form, to the sidebar, should I be doing this from predispatch in an Action Helper? Or from predispatch in a controller plugin? Why?
Thanks!
I recommend reading Using Action Helpers To Implement Re-Usable Widgets by Matthew Weier O'Phinney (ZF Lead).
In his example he uses public function preDispatch()
in an Action Helper to create a reusable Login/User-Widget.
I would use the ActionStack Action Helper to stack a call to the user controller. Stacking means, when you're done with this current action, let's call a new one before going to layout rendering.
This User controller would then be able to decide (based on Auth stored in registry) which content it should produce/take from cache). And this user controller action would use $this->_helper->viewRenderer->setResponseSegment('myusersidebar');
to let the main Zend_Layout simply call <?= $this->myusersidebar ?>
to echo the block.
So this not a controller plugin (except Action Stack is a controller plugin), not a controller predispatch, but simply the way of looping in Zend MVC stack by stacking several actions and rendering the layout at the end.
The action stacking is in fact related to layout composition and should be avoided for special requests (like ajax requests, they certainly do not need your user block). So you can either decide to do delay this process of stacking layout blocks on each Actions (and avoid stacking it for ajax actions), or add some code to remove the actions you want to stack when the Ajax Context loads (like the way Zend_Layout is disabled in AjaxContext).
The problem with a 'simple' predispatch treatment is that you may execute code to prepare your html block for requests that won't need this block (ajax requests, pdf requests, etc).
I actually believe doing it like that is not DRY. The user object would already be in the ZF app (Zend_Auth), thus additional duplicate logic is unnecessary IMO. All that's left is for your views to decide what to display based on the object's status.
Oh, I highly recommend a partial for this.
e.g. in your layout:
<?= $this->partial('userSidebar.phtml'); ?>
and then in your partial /application/layouts/userSidebar.phtml:
<div id="sidebar">
<?php if Zend_Auth::getInstance()->hasIdentity() : ?>
<?php $user = Zend_Auth::getInstance()->getIdentity() ?>
// do some user profiling stuffies
// if you need more information you should rather associate the user with those entities (else consider retrieving here or passing it as a parameter in the partial method)
<?php else : ?>
// not logged in
// do some login/registering stuffies
<?php endif ?>
</div>
I would use view helpers. This is from my first Zend project. It draws a link depends on whether a user is admin.
<?php
class TBB_View_Helper_PanelLink extends Zend_View_Helper_Abstract
{
public function panelLink($moduleName = 'customer')
{
$panelLink = "";
$auth = Zend_Auth::getInstance();
if($auth->hasIdentity()) {
$identity = $auth->getIdentity();
$username = $identity->username;
$userModel = new TBB_Model_Users();
$userID = $userModel->getUserIDByUsername($username);
if($userModel->isAdminUser($userID)) {
if($moduleName == 'customer') {
$panelLink = '<a class="span-4" href="admin/">Admin Panel</a>';
} else if($moduleName == 'admin') {
$panelLink = '<a class="span-4" href="/">Homepage</a>';
}
}
}
return $panelLink;
}
}