-- Vincent de Lau <[email protected]> wrote
(on Saturday, 14 March 2009, 12:52 PM +0100):
> I've noticed the perfomance hit on using Zend_View_Helper_Action, but don't
> know what a better approach would be. When asked, the only answer I get is:
> "Use view helpers!" but without further explanation or any argument aside
> from the performance hit. What I described above seems to me to be to
> large/complex for what a view helper is intended to. Sure, parts of this
> system could be done in helpers, but controlling what goes on a page?
>
> If performance is the major issue, that might weigh up against the
> flexibility of such a system. It would be just a design choice and
> effort should be taken to improve the dispatcher or create a lighter
> dispatcher for 'secondary' content.
Basically, using action() is akin to using your controllers as models,
which breaks several important principles of encapsulation.
The mantra of "use view helpers" stems from the fact that in MVC, views
are allowed to communicate with models in order to fetch content to
render. The goal, then, is to move all your business logic into models,
and then write view helpers that access these models (and, optionally,
format the information for rendering).
As an example, consider this view helper:
class My_View_Helper_RecentEntries extends Zend_View_Helper_Abstract
{
public $entryTemplate = '<li><a href="%s">%s</a></li>';
public function recentEntries()
{
$model = $this->view->entriesModel;
$recent = $model->fetchRecent();
$markup = '<ul class="recent-entries">';
foreach ($recent as $entry) {
$url = $this->view->url(array(
'controller' => 'articles',
'action' => 'view',
'id' => $entry->id,
),
'default',
true
);
$markup .= sprintf(
$this->entryTemplate,
$url,
$this->view->escape($entry->title)
);
}
$markup .= '</ul>';
return $markup;
}
}
In this case, we're pulling from a model we've injected into the view,
and then creating an unordered list which we return. In your view
script, you then simply echo the results:
<?php echo $this->recentEnties() ?>
and that's it. This tactic provides better encapsulation, provides
behavior that is easily testable, and is much more performant as there
is no need to lookup the controller and dispatch it.
Your suggestion that if performance is an issue with action(), effort
might go into improving the dispatcher or creating a lightweight version
makes sense in theory... but to do so actually exposes an important
point: modifying how the dispatch sequence works would actually
potentially break action().
Ironically, the method of using view helpers instead of action() makes
it *easier* to replace elements of Zend_Controller with your own
implementations, as you no longer need to worry that changing the
implementation will break the functionality.
> > -----Original Message-----
> > From: keith Pope [mailto:[email protected]]
> > Sent: Saturday, March 14, 2009 11:31 AM
> > To: Dan Ballance
> > Cc: [email protected]
> > Subject: Re: [fw-general] routeShutdown firing before action stack ...?
> >
> > You may want to read this blog
> >
> > http://www.rmauger.co.uk/2009/03/why-the-zend-framework-actionstack-is-
> > evil/
> >
> > and the performance guide in the manual, generally it is suggested to
> > use the placeholder view helper which gives you control over placement
> > or your own view helper.
> >
> > Hope that helps :)
> >
> > 2009/3/14 Dan Ballance <[email protected]>:
> > > Hi folks,
> > >
> > > I am trying to build a flexible 'widgetised' layout where the data
> > for which
> > > blocks go in which segments is held in the database.
> > >
> > > My current logic is to:
> > >
> > > read layout from the database and then load action stack with a
> > > controller/action for each block
> > > in my front controller plugin, on routeStartup, 'open bookend' each
> > segment
> > > with required markup
> > > loop through the blocks found in the database and write each block
> > output to
> > > the correct segment with action stack
> > > in my front controller plugin, on routeShutdown, 'close bookend' each
> > > segment with necessary markup.
> > > layout is finally renderred from the segments (top, left, default,
> > right,
> > > bottom) - where default is the output from the original
> > controller/action
> > > combo in the url
> > >
> > > The block data in the database tells me not just which
> > controller/action
> > > combo, but also the segment to write to. This is passed to action
> > stack as a
> > > param.
> > >
> > > I have created my own action controller which gets the segment param
> > which
> > > was passed to action stack and sets the segment to write the block to
> > in
> > > pre-dispatch.
> > >
> > > It's working reasonably well - except the end result is, for example
> > with
> > > the top segment:
> > >
> > > opening bookend, closing bookend, block 1, block 2, block 3
> > >
> > > What I want is:
> > >
> > > opening bookend, block 1, block 2, block 3, closing bookend
> > >
> > > I realise I haven't posted code yet ( can do that next, but didn't
> > want to
> > > post a huge message). At this stage i'm wondering if anyone can see a
> > flaw
> > > in my logic, am I misunderstanding the dispatch sequence?
> > >
> > > Any help / clues VERY gratefully received - i'm stuck!
> > >
> > > cheers,
> > >
> > > dan
> > >
> > >
> > >
> >
> >
> >
> > --
> > ----------------------------------------------------------------------
> > [MuTe]
> > ----------------------------------------------------------------------
>
--
Matthew Weier O'Phinney
Software Architect | [email protected]
Zend Framework | http://framework.zend.com/