1. Więcej o sekcjach

Jak wspomnieliśmy na początku, zadaniem sekcji jest wyświetlanie list. W klasycznych językach programowania można do tego celu wykorzystać pętle takie, jak for czy foreach. Jednak na dłuższą metę używanie zwykłych pętli jest dość kłopotliwe, gdyż stworzono je z myślą o uniwersalności. Musimy przez to przy okazji zmagać się z wieloma technicznymi aspektami ich działania. Przypuśćmy, że mamy tablicę, którą chcielibyśmy wyświetlić na stronie, ale w odwrotnej kolejności. Możemy to zrobić na kilka różnych sposobów:

$cnt = sizeof($tablica);
for($i = $cnt1; $i >= 0; $i--)
{
   echo wyswietl_element($tablica[$i]);
}

Możemy też spróbować użyć dodatkową funkcję:

foreach(array_reverse($tablica) as $i => $dane)
{
   echo wyswietl_element($dane);
}

Gdy taka lista jest jedna, nie stanowi to jeszcze takiego problemu. Niestety, sytuacja jest zupełnie inna. W szablonach listy pojawiają się dosłownie w ilościach hurtowych, w dodatku w wielu różnych kombinacjach: zagnieżdżone, niezagnieżdżone, czerpiące dane z tablic, z obiektów, generujące je w locie. Patrząc na kod jakiegoś algorytmu zapisany np. w PHP albo C, w rzeczywistości ciężko jest domyślić się, co to jest za algorytm, a nawet jak dokładnie działa bez dokładnego prześledzenia jego działania linijka po linijce. Podobnie jest z szablonami: gdy pętli będzie za dużo przeładowanych zbyt dużą liczbą szczegółów technicznych, cierpi na tym czytelność i nie tylko. W szablonach wyjątkowo dużo kodu może być powielone w wielu miejscach metodą kopiuj-wklej, ale zwykłe pętle w tym mocno przeszkadzają z powodu zrzucania zbyt wielu zadań na programistę. Dlatego pojawia się potrzeba stworzenia nowego mechanizmu zaprojektowanego specjalnie i wyłącznie do wyświetlania list. OPT odpowiada na nią przy pomocy sekcji, które starają się ukryć maksymalnie dużo zbędnych szczegółów przed twórcą szablonu, dzięki czemu tworzenie szablonu ma być dużo szybsze.

Spójrzmy, jak wygląda typowa sekcja umieszczona w szablonie, którą wyświetlimy np. listę aktualności w naszym panelu administracyjnym:

<table class="list">
 <thead>
  <tr>
   <th>#</th>
   <th>Tytuł</th>
   <th>Data</th>
   <th>Opcje</th>
  </tr>
 </thead>
 <tbody>
  <opt:section name="items">
   <tr>
     <td>{$items.id}</td>
     <td>{$items.title}</td>
     <td>{$items.date_formatted}</td>
    <td><a parse:href="'/news/edit/'~$items.id">Edytuj</a></td>
   </tr>
  </opt:section>
 </tbody>
</table>

To wszystko. Jak widać, konstrukcja sekcji po stronie szablonu jest maksymalnie uproszczona i do poprawnego działania wystarczy jedynie nadać jej nazwę. Zawartość znaczników opt:section opisuje wygląd pojedynczego elementu listy, a do jego danych możemy odwoływać się poprzez specjalną konstrukcję $nazwaSekcji.zmiennaElementu. W szablonie nie mówimy absolutnie nic o tym, skąd sekcja ma dane, jak po się po nich iteruje oraz jak współpracować z innymi sekcjami. W OPT musimy wychodzić z założenia, że takie informacje zależą w całości od skryptu, który używa szablonu i to tam powinny być one doprecyzowane. Zauważmy, że taką sekcję możemy bez trudu skopiować w zupełnie inne miejsce kodu i zacznie ona od razu poprawnie w nim działać praktycznie bez zmiany ani jednej linijki. Wyświetlenie listy w odwrotnej kolejności także nie stanowi problemu:

  <opt:section name="items" order="desc">
   <tr>
     <td>{$items.id}</td>
     <td>{$items.title}</td>
     <td>{$items.date_formatted}</td>
    <td><a parse:href="'/news/edit/'~$items.id">Edytuj</a></td>
   </tr>
  </opt:section>

A co zrobić, by ukryć całą tablicę, gdy lista nie będzie mieć żadnych elementów? Także i na to jest prosty sposób:

<opt:show name="items">
<table class="list">
 <thead>
  <tr>
   <th>#</th>
   <th>Tytuł</th>
   <th>Data</th>
   <th>Opcje</th>
  </tr>
 </thead>
 <tbody>
  <opt:section>
   <tr>
     <td>{$items.id}</td>
     <td>{$items.title}</td>
     <td>{$items.date_formatted}</td>
    <td><a parse:href="'/news/edit/'~$items.id">Edytuj</a></td>
   </tr>
  </opt:section>
 </tbody>
</table>
<opt:showelse>
 <p>Brak elementów</p>
</opt:showelse>
</opt:show>

Obudowujemy całą tablicę dodatkowym znacznikiem opt:show i przenosimy do niego atrybuty z opt:section, który teraz zaznacza jedynie miejsce, które ma być poddane iteracji.

Jeszcze raz podkreślamy dla utrwalenia: przeniesienie atrybutów jest niezwykle ważne. Gdybyśmy tego nie zrobili, OPT zrobiłby z opt:section oddzielną sekcję, zamiast powiązać ją z opt:show.