Mirin webspace

Nejbohatší život má ten, kdo žije s minimem nároků

12. 2. 2008 Zend Framework

Nový action view helper

Minulý týden jsem začal pracovat na kaledáři. Občas je možné ho na některém blogu (většinou blogy na wodpressu) vidět. Napadlo mě, že bych mohl vyzkoušet novou metodu, jak na to. V připravované verzi Zend Frameworku je spousta nových view helperů a jeden z nich mě zaujal, jedná se o Action view helper (neplést s action helpery, které jsou na něco úplně jiného). Tento view helper bude jedním ze způsobů, jak udělat něco jako widget. Další možností může být i použití ActionStack action helperu a stejnojmenného controller pluginu, které jsou také novinkami. O těch se dnes ale zmiňovat nebudu. Jak se ale už pomalu stává tradicí, použití nového Action view helperu má opět poměrně zásadní mouchy.

Základní myšlenka Action view helperu

Původně se měl tento helper měl jmenovat controller view helper, ale nakonec se to změnilo na action view helper. Prostřednictvím tohoto helperu můžeme v nějaké view šabloně vyvolat nějakou action určitého controlleru a výsledek tohoto volání pak v šabloně zobrazit. To nám umožňuje používat actions v controllerech jako zdroje výstupu kdekoli ve view. Je to jeden ze způsobů jak používat integrovat určité části aplikací do sebe - jednoduše agregovat výstupy.

Použití a příklad

Použití je docela jednoduché, stačí pouze helperu předat jakou kde a jakou action má zavolat s jakými parametry. Představme si, např. že někde na stránkách. v okrajovém sloupci chceme zobrazit poslední záznamy blogu, přičemž hlavní obsah stránky nemá s blogem nic moc společného.

./scripts/external/blogEntries.phtml
 
<h2>Last entries from my blog</h2>
<div id="blog-content">
 <!-- aggregate from Blog_IndexController::indexAction() -->
 <?php $this->action('index', 'index', 'Blog') ?>
</div>

Problémy

Vypadá to pěkně, ale je tu jeden zásadní problém. Pokud po vyvolání action helperu potřebujeme ještě stále provádět obsluhu dalších actions, máme smůlu. Já jsem chtěl použít action view helper k implementaci kalendáře do pravého menu na blogu. Upravil jsem aktuální kód zhruba takto.

./modules/blog/IndexController.php
 
//===========================================
/**
 * Action handler for the index page.
 */
public function indexAction()
{
 //right block
 $this->righBlock();
 
 $this->view->mainInfo="index content";
}
 
//===========================================
/**
 * right bar
 */
public function righBlock()
{
 $this->view->rightBlock=$this->view->render("blogMenu.phtml");
}
 
//===========================================
/**
 * Renders the calendar for the article archive.
 * Is called from the Zend_View_Helper_Action as the widget.
 */
public function articleCalendarArchiveAction()
{
 $monthArchive=$this->_getMonthArchive();
 
 $this->view->articleArchive=$monthArchive;
}

šablona pro pravý blok

./modules/blog/views/scripts/blogMenu.phtml
 
<h2>Calendar</h2>
<!-- calendar archive widget -->
<?php
  echo $this->action("articleCalendarArchive","index","blog");
?>

šablona pro hlavní stránku

./modules/blog/views/scripts/index/index.phtml
 
...
<div id="content">
 <div id="main">
  <?php echo $this->mainInfo?>
 </div>
 <div id="menu">
  <?php echo $this->rightBlock?>
 </div>
</div>

Nejdříve nastavím pravý blok, v něm přes action view helper vykreslím kalendář, pak dokončím index action a viewRenderer mě pak vykreslí celou stránku dle šablony index.phtml i s kalendářem. A tady je právě zásadní problém, nezobrazí se nic!

Chyba je v novém action view helperu. Ten musí normálně provést dispatch našeho požadavku na kalendář a pro zobrazení výsledku se použije co jiného, než viewRenderer, ten samý viewRenderer, který nám pak má vykreslit hlavní index.phtml. Jenže na to viewRenderer není uzpůsoben, jakmile něco vykreslí (v tomto případě kalendář), interně si nastaví _noRender na true a šmytec, tím pádem index.phtml už neuvidíme. Jedná se tedy o poměrně závažnou chybu, která znemožňuje použití action view helperu dříve, než před vykreslováním finální šablony. Jako workaround lze použít to, že viewRenderer "odblokujeme" ručně, pomocí metody setNoRender(). V našem případě tedy po kreslení menu.

/**
 * right bar
 */
public function righBlock()
{
 $this->view->rightBlock=$this->view->render("blogMenu.phtml");
 //unblock viewRenderer - workaround for a bug in the Zend_View_Helper_Action
 $this->_helper->viewRenderer->setNoRender(false);
}

Nakonec to tedy snad nějak půjde, nicméně je dobře vidět, že pokud člověk trochu odbočí od hlavní vyšlapané cesty, může často šlápnout do ho…


Komentáře (0)

Komentáře jsou uzavřeny.