3. Budujemy szablon główny

Zazwyczaj szablony używane przez witryny WWW są zmodularyzowane. Nagłówek i stopka pozostają najczęściej identyczne, a zmienia się jedynie zawartość, dlatego powinny być umieszczone we wspólnym szablonie, w którym osadzana jest reszta treści charakterystyczna dla aktualnie wyświetlanego modułu. Tworząc szablon główny w Open Power Template 2, musimy zwracać baczną uwagę przede wszystkim na prolog dokumentu oraz DTD. Gdybyśmy zapisali je bezpośrednio, na domyślnych ustawieniach OPT zachowałby je dla siebie i nie przesłał do przeglądarki. Dlatego aby ułatwić osadzanie tych elementów w kodzie wynikowym, mamy do dyspozycji instrukcje opt:prolog oraz opt:dtd. Ponadto skorzystamy z pomocy "pojemnika" opt:root, który tworzy nam element główny, w którym możemy sobie zapisać pozostałą treść. Nasz szablon może wyglądać tak, jak poniżej:

<?xml version="1.0" ?>
<opt:root>
<opt:prolog />
<opt:dtd template="xhtml10" />
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
  <head>
    <title>Moja strona WWW</title>
    <!-- pozostale znaczniki -->
  </head>
  <body>
    <!-- wyglad naglowka -->
 
    <!-- poczatek kodu wyswietlania modulow -->
    <opt:section name="modules">
      <opt:include from="modules" />
    </opt:section>
    <!-- koniec kodu wyswietlania modulow -->
 
    <!-- wyglad stopki -->
  </body>
</html>
</opt:root>

Prolog widoczny na początku szablonu nie jest przesyłany do przeglądarki, lecz parsowany przez Open Power Template i zachowywany do własnej wiadomości. Dopiero instrukcja opt:prolog generuje prolog "wyjściowy". Posiada ona identyczne argumenty, jak te, które możemy umieszczać w tradycyjnym prologu, lecz jeśli nie podamy żadnego, OPT spróbuje użyć domyślnych wartości. Kolejnym uproszczeniem jest instrukcja opt:dtd, w której zamykamy blok DTD. Możemy to zrobić, klepiąc wszystko ręcznie:

<opt:dtd><![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
]]></opt:dtd>

Ręczne definiowanie bloku CDATA wymaga, aby był on zamknięty w sekcji CDATA. Bez obaw, OPT zadba o to, aby wysyłany do przeglądarki dokument był w pełni poprawny i na pewno nie będzie próbować drukować zbędnych znaczników.

Oprócz tego, mamy do dyspozycji zestaw predefiniowanych, gotowych "szablonów" wybieranych atrybutem template, gdy nie chce nam się pamiętać całego DTD. Mają one proste, intuicyjne nazwy, jak np. xhtml10, html4 czy html5 i są zgodne z tym, co zalecają odpowiednie standardy.

Dopiero po tych dwóch znacznikach możemy wstawić <html> i zająć się definiowaniem wyglądu dokumentu. Przy okazji zwróćmy uwagę na sposób wyświetlania treści zależnej od modułu. Jak powinno być wiadome, w OPT pracujemy z obiektami zwanymi widokami. Każdy widok to szablon oraz towarzyszące mu dane ze skryptu, dzięki czemu każdy szablon ma niezależną przestrzeń zmiennych i unikamy kolizji nazw. Poszczególne moduły mogą generować takie obiekty widoków i zwracać je jako swój wynik wykonania do kontrolera:

public function action()
{
  $view = new Opt_View('module_index.tpl');
  $view->zmienna = 'foo';
 
  return $view;
} // end action();

Tam mogą one zostać zapakowane w sekcję i wrzucone do głównego szablonu. Instrukcja opt:include domyślnie renderuje właśnie obiekty widoków, a co więcej, potrafi renderować je bezpośrednio z sekcji tak, jak to pokazane jest na przykładzie. Poniżej zaś widzimy przykładowy kod, który przygotowuje dane:

$moduleViews = array();
foreach($this->currentModules as $module)
{
  $view = $module->action();
  if($view instanceof Opt_View)
  {
    $moduleViews[] = array('view' => $view);
  }
}
 
$layout = new Opt_View('layout.tpl');
$layout->modules = $moduleViews;
 
$output->render($layout);

W ten sposób skonstruowaliśmy zarówno główny szablon naszej strony, jak i podstawowy kod do jego obsługi.