Mirin webspace

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

15. 3. 2008 - Komentáře (4) Zend Framework

Zend_Layout

S verzí 1.5 Zend Frameworku, přichází i podpora layoutu. Jedná se o jednu s velmi žádaných věcí, která ve verzi 1.0 chyběla. Ačkoli i dříve se layout dal implementovat pomocí front controller pluginu, je jeho podpora přímo vývojáři určitě dobrým krokem a do frameworku určitě patří. Implementace layoutu je zároveň integrována s novými view helpery. Pokusím se popsat základní principy, jak layout v Zend Frameworku funguje. Pro další čtení je potřeba mít základní tušení, jak funguje MVC v Zend Frameworku.

Layout, (často se zmiňuje také označení Two Step View), umožňuje obalit celý obsah aplikace do kabátku - layoutu, který obvykle představuje view šablona. Implementace layoutu ve frameworku se skládá z několika tříd, které jsou součástí balíčku Zend_Layout. Jedná se zejména o samotnou třídu Zend_Layout a třídy, které napomáhají integraci layoutu do MVC implementace, která je v Zend Frameworku. Implementace je poměrně flexibilní, takže je možné layout měnit, zakazovat a povolovat pro jednotlivé actions, měnit nastavení adresářů a view šablon pro layout atd. Jak jsem řekl, je implementace provázána na MVC infrastrukturu frameworku, nicméně layout lze používat i bez ní, samostatně. Já jsem jí samozřejmě na tomto blogu použil s MVC, proto se možností použití bez MVC zabývat nebudu.

Jak jsem se již zmínil, již dříve se dal princip layoutu implementovat front controller pluginem, podobně je použit i Zend_Layout, který využívá jak pluginu, tak action helperů a integraci s viewRendererem. Implementace také využívá nových view helperů a placeholderů, což je nový typ view helperu. Základní použití je asi následující. Máme šablonu layout.phtml v adresáři /path/to/layouts/ - náš kabátek.

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>My Site</title>
</head>
<body>
<?php
    // fetch 'content' key using layout helper:
    echo $this->layout()->content;
 
    // fetch 'rightBlock' key using placeholder helper:
    echo $this->placeholder('Zend_Layout')->rightBlock;
 
    // fetch layout object and retrieve various keys from it:
    $layout = $this->layout();
    echo $layout->bar;
    echo $layout->baz;
?>
</body>
</html>

Inicializace layoutu je velmi jednoduchá, v bootstrapu zavoláme statickou metodu

Zend_Layout::startMvc('/path/to/layouts/')

která vytvoří instanci Zend_Layout. Jako parametr dostává cestu k adresáři s layout view skripty. Jako parametr můžeme použít i pole s konfigurací layotu nebo Zend_Config, více o konfiguraci v manuálu.

Tak a teď to nejdůležitější, jak do layoutu dostat obsah. Ve výše zmíněném layout view skriptu je demonstrováno použití layout view helperu

$this->layout()->content

a layout placeholderu

$this->placeholder('Zend_Layout')->rightBlock

jsou to dvě rovnocenné možnosti jak se dostat k proměnným layoutu. Je totiž důležité si uvědomit, že layout šablona je použita skrz view objekt, který si drží viewRenderer. Jakékoli proměnné, které tedy do tohoto view objektu nastavíte, můžete klidně v layout šabloně použít - to je první možnost, jak vytvořit obsah layotu. Lepší je to ale udělat jinak.

Response segmenty a obsah layoutu

Response objekt v MVC Zend frameworku podporuje takzvané response segmenty, v podstatě tak lze výsledný zobrazovaný celek rozdělit na určité samostatné části a manipulovat s nimi. Response segmenty se dají pojmenovat. Implicitně viewRenderer používá segment jménem default pro výstup controller akcí. Jak jsem se již zmínil, layout funguje jako front controller plugin a právě pomocí tohoto pluginu se dosahuje toho, že jednotlivé segmenty se převádějí na view proměnné v layout šabloně, přičemž právě default segment se převede na proměnnou content. Takže pokud v našem příkladu budeme mít třeba controller

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
      $this->rightBlock();
    }
 
    public function righBlock()
    {
      $category=new Category();
      $this->view->categories=$category->getAll();
 
      //Renders rightblock into 'rightBlock' segment
      $response = $this->getResponse();
      $response->insert('rightBlock', $this->view->render('rightBlock.phtml'));
 
      unset($this->view->categories);
    }
}

a šablonu scriptsPath/foo/bar.phtml

 <span style="color:red">this is main content</span>

pak v naší layout šabloně layout.html dojde k tomu, že v místě

$this->layout()->content

se dostaneme k obsahu naší bar.phtml šablony - použil se layout view helper a v místě

$this->placeholder('Zend_Layout')->rightBlock

budeme mít obsah našeho pravého bloku - použil se layout placeholder view helper.

V této souvislosti je dobré zmínit i nový ActionStack front controller plugin a a stejnojmenný action helper, pomocí něhož si můžeme nadefinovat posloupnost akcí. Řekl bych, že to bude i doporučovanější metoda, než výše uvedený postup s volaní public metody. Nezkoušel jsem to, ale mohlo by to vypadat asi nějak takto.

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
      $this->_helper->actionStack('right-block', 'Foo','default');
    }
 
    public function righBlockAction()
    {
      $category=new Category();
      $this->view->categories=$category->getAll();
 
      //Renders right block into 'rightBlock' segment
      $this->_helper->viewRenderer->setResponseSegment('rightBlock');
 
      unset($this->view->categories);
    }
}

To je tak asi k základům použití a funkce layoutu všechno. Samozřejmě, že layout má spoustu dalších možností namátkou třeba přepínání view šablony, vypínání layoutu, nastavování konfigurace, jak na to se lze dovědět v Zend framework manuálu.


Komentáře (4)

  1. Tomáš Fejfar - 21. 4. 2008 18:08

    Mam k tomuhle drobný dotaz :) Co když potřebuju zavolat akci z jiného kontrolleru?! Třeba konkrétně u vytváření widgetů přece nebudu widgety cpát pokaždé do jednotlivých controllerů, ale hoim si jeden controller ve kterém budou zapouzdřené jednou pro vždy...

  2. Tomáš Fejfar - 21. 4. 2008 18:39

    Ha, tak se omlouvám, nevšim jsem si, že syntaxe je ActionStack(action,controller,modul) - myslel sem, že to jsou jen další actions ^^

  3. DarkStar - 8. 7. 2008 14:42

    Ahoj,
    Ked uz tu mas ten tutorial k layoutom,
    chcel by som sa ta spytat ze ked na nejakej stranke
    chcem pouzit iny layout, ako to spravim?
    Dik za odpoved

  4. koubel - 13. 7. 2008 11:24

    [3] - Dotazy prosím směruj třeba na zend framework fórum, jinak v dokumentaci se píše něco ve smyslu

    public function bazAction()
        {
            // use different layout script with this action:
            $this->_helper->layout->setLayout('foobaz');
        }
    

Komentáře jsou uzavřeny.