O panie, OPT 1.x, a OPT 2.x to dwie zupełnie różne bajki. Równie dobrze mógłbyś się czepiać, że w PHP3 nie było klas abstrakcyjnych

.
E_NOTICE jest domyślnie wyłączany przez wiele systemów szablonów na czas wykonywania (nawet takich, gdzie pisze się w PHP). Sprawdzanie w kółko czy coś nie jest puste wcale nie jest szybsze, a udowodnił to Smarty 3, gdzie postąpiono w taki sposób i szablony wykonują się dwa razy wolniej. Ponadto jak Ci to przeszkadza, OPT akurat daje możliwość ustawienia innego trybu raportowania błędów na czas wykonywania szablonu...
Konkatenacja -> przecież w OPT był i jest operator konkatenacji. OPT robi z kropki mądrzejszy użytek niż PHP, a jak nie patrzyłeś do dokumentacji, ani nawet tutoriala, gdzie chyba każdy pokazywał, do czego kropka służy, to już jest to Twój problem.
Konieczność tworzenia listy używanych funkcji -> bo szablon nie jest od tego, by w nim korzystać z dowolnej funkcji. Potrzebny Ci
mysql_connect() tam? OPT 2.x ma dużo bardziej rozbudowaną listę funkcji domyślnych i np. ja jedyne, co podpinam, to router do generowania URL-i, a tak korzystam wyłącznie z domyślnych funkcji i instrukcji. Nawet w rozbudowanym projekcie.
Czytelność szablonów -> nigdzie nie powiedziałem, że nie musi dbać. Rozmawiamy o wydajności. Czytelny szablon PHP wymusza konieczność używania wolniejszych konstrukcji PHP. Czytelny szablon OPT dalej pozwala kompilatorowi na korzystanie z szybszych, ale mniej czytelnych konstrukcji PHP.
Cytat
Jeżeli chcesz mieć naprawdę łatwe w użyciu narzędzie (dość uniwersalne) do wyświetlanie bardziej zaawansowanych struktur to w opt tworzysz plugin czyli bądź co bądź również "trzeba przygotowywać w nienaturalny zupełnie sposób, klepiąc kod PHP". Chociażby przykład struktury drzewa.
W PHP klepiesz jedynie algorytm czyli rzecz, do której PHP się nadaje. Kod HTML, do którego PHP się nie nadaje, zostaje cały czas w szablonie, czego nie można powiedzieć o helperach pisanych dla szablonów PHP. Jedyne instrukcje w OPT 2, które generują jakieś statyczne wyjście, to
opt:prolog oraz
opt:dtd (a i tu nawet niekoniecznie) z oczywistych powodów. Ani jedna poza tym nie zakłada, że np. pole formularza musi być w znacznikach DD/DT, że drzewko musi być na liście UL, a na OL nie może, że okruszki są renderowane na bazie listy UL, że błąd to znacznik DIV z klasą "error" itd. Helpery dla PHP mają takie rzeczy zaklepane na sztywno i żeby je zmienić musisz albo obiektowo informować, że ma być inny znacznik, albo przepisać cały helper. Nie pisz, że przecież jak piszę, to wiem, czego potrzebuję, bo prawda jest taka, że:
- Nie muszę wiedzieć, jaki layout ostatecznie dostarczy grafik.
- Jak używam frameworka, to tam helpery już
są.
Ponadto OPT 2.x ma już tyle gotowych rzeczy zaimplementowanych (a w 2.1 będzie jeszcze więcej), że naprawdę coraz ciężej już znaleźć sytuację, gdzie czegoś brakuje i człowiek jest zmuszony do napisania własnej instrukcji.
Prosisz o kilka przykładów, ok:
Kod
<opt:snippet name="loopBody">
<h1>{$item.title}</h1>
{$item.data}
</opt:snippet>
<!-- wyrenderuj listę 1 przy pomocy predefiniowanego wcześniej kodu -->
<opt:section name="list1" opt:use="loopBody" />
<!-- wyrenderuj listę 2 przy pomocy predefiniowanego wcześniej kodu -->
<opt:section name="list2" opt:use="loopBody" />
<!-- wyrenderuj listę 3 przy pomocy predefiniowanego wcześniej kodu -->
<opt:section name="list3" opt:use="loopBody" />
<!-- wyświetl pojedynczy element ze zmiennej $item przy pomocy predefiniowanego wcześniej kodu -->
<opt:insert snippet="loopBody" />
Snippet można umieścić w oddzielnym pliku TPL i dalej nie będzie to mieć żadnego wpływu na wydajność, a kod jest tak samo szybki, jak wtedy, gdy treść sekcji jest określona explicite.
Renderowanie drzewka:
Kod
<opt:tree name="tree">
<opt:list>
<ul>
<opt:content />
</ul>
</opt:list>
<opt:node>
<li>{$tree.text}
<opt:content />
</li>
</opt:node>
</opt:tree>
Wszystkie helpery we frameworkach, jakie widziałem do tego problemu, opierają się na rekurencji, co oznacza, że głębokość takiego drzewka jest ograniczona i w dodatku zależna od projektu (w jednym widok może być odpalany płycej, w drugim głębiej, przez co mamy mniej stosu do dyspozycji). OPT posiada algorytm iteracyjny, więc można nawet drzewo o głębokości 1000 wyrenderować, a od wersji 2.1 będzie można go nawet wymieniać (i będzie ich więcej) bez zmiany szablonu.
Instrukcje dynamiczne w dużej części zależą od tego, jakiego formatu danych się do nich użyje, ale np. sekcja na danych tablicowych:
Kod
<opt:section name="foo">
<p>{$foo.item}</p>
</opt:section>
kompilowana do szybszej pętli
for, a nie
foreach. Od wersji 2.1 OPT potrafi optymalizować zwykłe wyrażenia, a także określać, kiedy warto użyć zmiennej tymczasowej, a kiedy nie.
Mi osobiście się nic nie zlewa w składni XML (a nawet więcej: wolę, by instrukcje były dyskretnie pochowane, niż żeby mi się poniewierały tak, że nie widzę nawet, gdzie mam w znaczniku symbol <, a gdzie >. Ponadto klamerki są wciąż zachowane dla wyrażeń w tekście statycznym, jako że standard XML nie zabrania przetwarzania treści statycznej, jak to niektórzy "znawcy" mi kiedyś sugerowali. Ponadto XSLT jest też w dużej części nastawiony na obróbkę danych, OPT koncentruje się na wyświetlaniu. Dlatego podany przez Ciebie ostatni przykład jest niezgodny z filozofią OPT, ponieważ ja zakładam, że szablon dostanie już przefiltrowane dane. Nawiasem mówiąc co niby ten kod ma robić, poza tym że coś robić z URL-em?
Przykład z pętlą:
- Zgubiłeś instrukcję warunkową, która sprawdzi czy dane faktycznie są tablicą.
- Ja mam
<? wyłączony na serwerze, więc guzik uruchomię, a nie szablon

.
- Masz na sztywno powiedziane, że tag jest tablicą. A ja będę chamski, użyję Doctrine i powiem, że w tym miejscu potrzebuję hydrację do obiektów, ponieważ coś chcę jeszcze na tym wykonać.

W innym miejscu zrobisz obiekt, a ja znów będę chamski i stwierdzę, że tam jednak obiektów nie potrzeba i chcę mieć hydrację do szybszych tablic. Przykład z życia wzięty

.
- Brak ochrony przed HTML injection.
- Muszę pamiętać, że metoda X dostępna jest przez
$this, Y jakąś inną drogą, Z jest metodą statyczną, A zwykłą funkcją...
Ograniczenia posiada każdy język. W PHP nie zrobisz łatwo czegoś takiego:
Kod
<opt:if>
<opt:condition test="$warunek1">
<p>Warunek 1</p>
</opt:condition>
<p>Treść bezwarunkowa</p>
<opt:condition test="$warunek2">
<p>Warunek 2</p>
</opt:condition>
<opt:condition test="$warunek3">
<p>Warunek 2</p>
</opt:condition>
<p>Treść bezwarunkowa</p>
<opt:else>
<p>Alternatywa ostateczna</p>
</opt:else>
</opt:if>
W przypadku OPT nie ukrywam, że np. pisanie w nim algorytmu Dijkstry będzie w nim okrutną męczarnią. Ja wyznaję zasadę, że wolność to nie samowola, a skoro nie samowola, to są pewne reguły. Pewne reguły mówią, że pewnych rzeczy w szablonach się nie robi, a jeśli już, to nie chcę wiedzieć, że one się robią. Stosuję się do tego ściśle, dlatego nie mam problemów z tym, że nie mogę sobie silni policzyć między jednym, a drugim tagiem (no dobra, w sumie z
opt:repeat da się to prosto zrobić

), ponieważ uważam, że to jest sprawa innej warstwy abstrakcji.
PS. Podbijam poprzeczkę

Kod
<p class="tags">
<opt:section="tags" order="desc">
<a parse:href="$tag.url">{$tag.name}</a>
</opt:section>
</p>