<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: yes -->
<sect1 id="learning.quickstart.create-layout">
    <title>Utworzenie layoutu</title>

    <para>
        Jak nie trudno zauważyć, skrypty widoków z poprzedniej części zawierały jedynie fragmenty
        kodu <acronym>HTML</acronym>, 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ą.
    </para>

    <para>
        Teraz należy umieścić generowaną treść w pełnoprawnej stronie <acronym>HTML</acronym>.
        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.
    </para>

    <para>
        Zend Framework używa dwóch wzorów projektowych przy implementacji layoutów: <ulink
        url="http://martinfowler.com/eaaCatalog/twoStepView.html">Widok dwustopniowy
        (Two Step View)</ulink> oraz
        <ulink
        url="http://java.sun.com/blueprints/corej2eepatterns/Patterns/CompositeView.html">Widok
        złożony (Composite View)</ulink>.
        <emphasis>Widok dwustopniowy</emphasis> jest najczęściej powiązany z <ulink
        url="http://www.martinfowler.com/eaaCatalog/transformView.html">Widokiem przekształconym
        (Transform View)</ulink> - 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.
        <emphasis>Widok złożony</emphasis> natomiast, zakłada tworzenie jednego bądź wielu
         autonomicznych widoków bez relacji rodzic-potomek.
    </para>

    <para>
        <link linkend="zend.layout">Zend_Layout</link> 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.
    </para>

    <para>
        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
        <emphasis>pojemników (placeholders)</emphasis>, które umożliwiają dostęp do takich
        elementów z poziomu lokalnego skryptu widoku.
    </para>

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

    <programlisting language="shell"><![CDATA[
% 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.
]]></programlisting>

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

    <programlisting language="ini"><![CDATA[
; application/configs/application.ini

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

    <para>
        W rezultacie plik <acronym>INI</acronym> powinien wyglądać następująco:
    </para>

    <programlisting language="ini"><![CDATA[
; 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
]]></programlisting>

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

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

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

    <programlisting language="php"><![CDATA[
// application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initDoctype()
    {
    }
}
]]></programlisting>

    <para>
        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 <classname>View</classname>. Potem można pobrać 
        obiekt i go użyć.
    </para>

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

    <programlisting language="ini"><![CDATA[
; application/configs/application.ini

; Dodanie do sekcji [production]:
resources.view[] =
]]></programlisting>

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

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

    <programlisting language="php"><![CDATA[
// application/Bootstrap.php

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

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

    <programlisting language="php"><![CDATA[
<!-- 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>
]]></programlisting>

    <para>
        Za pomocą view helpera <methodname>layout()</methodname> 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.
    </para>

    <para>
        Należy zwrócić uwagę na użycie view helpera <methodname>headLink()</methodname>. Jest to
        prosty sposób na zachowanie kontroli nad elementami &lt;link&gt; dodawanymi w
        różnych miejscach aplikacji oraz na wygenerowanie kodu <acronym>HTML</acronym>
        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 <methodname>headLink()</methodname>(na generowanej
        stronie pojawi się automatycznie).
    </para>

    <note>
        <title>Punkt kontrolny</title>

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