Utworzenie layoutu

Jak nie trudno zauważyć, skrypty widoków z poprzedniej części zawierały jedynie fragmenty kodu HTML, a nie całe strony. Jest to zamierzone i ma na celu przygotowanie akcji tak, aby zwracały jedynie zawartość związaną z samą akcją, a nie aplikacją jako taką.

Teraz należy umieścić generowaną treść w pełnoprawnej stronie HTML. Przydatne jest również nadanie całej aplikacji jednolitego, zwięzłego wyglądu. Aby to osiągnąć zostanie użyty globalny layout (wzór) strony.

Zend Framework używa dwóch wzorów projektowych przy implementacji layoutów: Widok dwustopniowy (Two Step View) oraz Widok złożony (Composite View). Widok dwustopniowy jest najczęściej powiązany z Widokiem przekształconym (Transform View) - podstawową cechą jest założenie, że aplikacja tworzy widok podrzędny, który zostaje umieszczony w widoku głównym (layout) i dopiero taki - złożony widok jest przetwarzany do pokazania użytkownikowi. Widok złożony natomiast, zakłada tworzenie jednego bądź wielu autonomicznych widoków bez relacji rodzic-potomek.

Zend_Layout jest komponentem, który łączy te wzorce w aplikacji Zend Framework. Każdy skrypt widoku (view script) posiada własne elementy i nie musi zajmować się wyświetlaniem elementów wspólnych dla całej strony.

Mogą powstać sytuacje, w których niezbędne okaże się umieszczenie globalnych elementów w pojedynczym widoku. W tym celu Zend Framework udostępnia szereg pojemników (placeholders), które umożliwiają dostęp do takich elementów z poziomu lokalnego skryptu widoku.

Aby rozpocząć korzystanie z Zend_Layout należy najpierw poinstruować bootstrap aby włączył zasób Layout. Można to osiągnąć za pomocą komendy zf enable layout (w katalogu tworzonego projektu):

% zf enable layout
Layouts have been enabled, and a default layout created at
application/layouts/scripts/layout.phtml
A layout entry has been added to the application config file.

Tak jak jest to napisane w potwierdzeniu komendy, plik application/configs/application.ini został zaktualizowany i zawiera następujący wpis w sekcji production:

; application/configs/application.ini

; Dodane do sekcji [production]:
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"

W rezultacie plik INI powinien wyglądać następująco:

; application/configs/application.ini

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

Dodany zapis powoduje, że aplikacja szuka skryptów widoku w katalogu application/layouts/scripts. Należy zauważyć, iż taki katalog wraz z plikiem layout.phtml zostały utworzone w strukturze projektu przez narzędzie wiersza poleceń zf.

Następną przydatną rzeczą będzie upewnienie się, że deklaracja XHTML DocType jest umieszczona i poprawnie sformułowana. Aby to osiągnąć należy dodać zasób do bootstrapa.

Najprostszym sposobem na dodanie zasobu bootstrap jest utworzenie chronionej metody o nazwie zaczynającej się na _init. Celem jest zainicjalizowanie deklaracji DocType więc nowa metoda w klasie bootstrap może się nazywać _initDoctype():

// application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initDoctype()
    {
    }
}

W ciele metody należy powiadomić zasób widoku aby użył odpowiedniego DocType. Tylko skąd wziąć obiekt widoku? Najłatwiejszym rozwiązaniem jest zainicjalizowanie zasobu View. Potem można pobrać obiekt i go użyć.

Aby zainicjalizować zasób widoku należy dodać następującą linijkę do pliku application/configs/application.ini w sekcji production:

; application/configs/application.ini

; Dodanie do sekcji [production]:
resources.view[] =

Ten zapis inicjalizuje widok bez żadnych opcji (pisownia '[]' oznacza, że "view" jest tablicą bez żadnych kluczy ani wartości).

Teraz, skoro widok jest skonfigurowany, można wrócić do metody _initDoctype(). W niej należy upewnić się, że zasób View został zainicjowany (na podstawie zapisów w pliku konfiguracyjnym), pobrać obiekt widoku i go skonfigurować:

// application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initDoctype()
    {
        $this->bootstrap('view');
        $view = $this->getResource('view');
        $view->doctype('XHTML1_STRICT');
    }
}

Po zainicjalizowaniu Zend_Layout i ustawieniu deklaracji Doctype, należy utworzyć główny layout strony:

<!-- application/layouts/scripts/layout.phtml -->
<?php echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Zend Framework Quickstart Application</title>
  <?php echo $this->headLink()->appendStylesheet('/css/global.css') ?>
</head>
<body>
<div id="header" style="background-color: #EEEEEE; height: 30px;">
    <div id="header-logo" style="float: left">
        <b>ZF Quickstart Application</b>
    </div>
    <div id="header-navigation" style="float: right">
        <a href="<?php echo $this->url(
            array('controller'=>'guestbook'),
            'default',
            true) ?>">Guestbook</a>
    </div>
</div>

<?php echo $this->layout()->content ?>

</body>
</html>

Za pomocą view helpera layout() pobierana jest zawartość przeznaczona do wyświetlenia (znajduje się w zmiennej "content"). Można ją umieszczać w innych częściach layoutu ale w większości przypadków takie podejście wystarczy.

Należy zwrócić uwagę na użycie view helpera headLink(). Jest to prosty sposób na zachowanie kontroli nad elementami <link> dodawanymi w różnych miejscach aplikacji oraz na wygenerowanie kodu HTML dla tych elementów w pliku layoutu bądź innego skryptu widoku. Jeśli zajdzie potrzeba dodania dodatkowego arkusza CSS w pojedynczej akcji to można to zrobić używając headLink()(na generowanej stronie pojawi się automatycznie).

Punkt kontrolny

Teraz należy udać się pod adres "http://localhost" i sprawdzić efekty oraz wygenerowany kod. Powinien pojawić się nagłówek XHTML, elementy head, title oraz body.