Ale po kolei. Master templates, które będą figurować w polskiej dokumentacji jako "szablony kompilacyjne", to specjalne szablony ładowane tylko w momencie inicjacji kompilatora. Ich działanie wyjaśnię przykładowo, bo pewnie nie wszyscy znają i używają np. instrukcji bind. Otóż w OPT są dwie takie instrukcje: bind oraz bindEvent, których zadaniem jest "przechowanie" fragmentu kodu szablonu do późniejszego użycia. W przeciwieństwie do capture przechwytującego wyjściowy kod HTML, taka wstawka zachowuje swój dynamiczny charakter, tj. jeśli po jej użyciu zmienimy dane i walniemy ją gdzieś ponownie, wprowadzone zmiany będą widoczne w wyniku. Instrukcje te są aktywne tylko podczas kompilacji, gdyż po jej wykonaniu informacja o ich istnieniu jest gubiona; zostaje tylko efekt działania w postaci wstawek, które umieściły posiadany przez siebie kod w różnych miejscach. Popatrzmy, co się z tym wiąże. Mamy pięć szablonów, w pierwszym definiujemy dodatkowo wszystkie wstawki, z których korzystają pozostałe cztery. Kiedy kompilowane są wszystkie naraz, wszystko jest OK. Ale wystarczy, żeby kompilacji ulegał tylko jeden z nich, np. trzeci. Wtedy okaże się, że nie zostaną doń wstawione żadne wstawki, ponieważ kompilator nie przetworzył definiującego je szablonu. Tu do akcji wchodzą szablony kompilacyjne. Są one ładowane tylko w momencie inicjacji kompilatora i służą temu, aby właśnie w nich poumieszczać takie wstawki, dzięki czemu będą one zawsze dostępne, kiedy najdzie nas potrzeba kompilowania czegoś :).
Kolejna sprawa to rendering drzew, o którym trąbiłem już jakiś czas. OPT 1.1.0 będzie wreszcie zawierać ten element. Instrukcja do wykonywania tego, tree, jest właściwie odmianą sekcji: pobiera te same parametry, co sekcja, może być stosowana z show, wpływają na nią te same ustawienia itd. Jedyna różnica to rezultat. Popatrzmy:
<ol> {tree=mytree} {leaf} <li>{$mytree.title}</li> {/leaf} {opening} <li>{$mytree.title}<ol> {/opening} {closing} </ol></li> {/closing} {treeelse} <li>No tree provided.</li> {/tree} </ol>
Wewnątrz znaczników {tree} i {/tree} mamy trzy tagi - opening, leaf oraz closing. Określają one wygląd poszczególnych elementów drzewa: elementu otwierającego nowy poziom, liścia oraz zamknięcia poziomu. W elementach dla takiego drzewa należy umieścić dodatkowy blok: depth definiujący ich głębokości (patrz: artykuł "Drzewa w PHP i MySQL"), na podstawie którego algorytm wylicza odpowiednie zależności i dobiera sposób jego wyświetlenia. Dodam, że ciekawscy mogą spróbować ustawić parametr "reversed" istniejący tylko dla zachowania kompatybilności z sekcją, ale rezultat nie jest interesujący - bo jak niby wyświetlić drzewko od tyłu? :)
Drzewka przeważnie renderuje się z użyciem HTML-owych wyliczeń: OL lub UL, dlatego nie ma sensu za każdym razem powtarzać tego samego opisu wyglądu drzewa. Można go wsadzić do nowej instrukcji bindGroup, tę umieścić w szablonie kompilacyjnym i po prostu podpinać raz zdefiniowany wygląd do kolejnych drzew:
{bindGroup name="mytree"} {leaf} <li>{$mytree.title}</li> {/leaf} {opening} <li>{$mytree.title}<ol> {/opening} {closing} </ol></li> {/closing} {/bindGroup} <p>Drzewko 1:</p> {show=tree1} <ol> {tree} {use snippet="mytree"/} {/tree} </ol> {showelse} <p>No tree provided.</p> {/show} {show=tree2} <ol> {tree} {use snippet="mytree"/} {/tree} </ol> {showelse} <p>No tree provided.</p> {/show}
PS. Zauważcie, że wewnątrz bindGroup używamy bloków $mytree.cośtam, a nasze drzewka to tree1 i tree2. Niezgodność nazw? W wersji 1.0.0 - owszem. Nowy OPT sobie automatycznie sam przekonwertuje nazwę.
Z nowym OPT można zintegrować system dzielenia wyników na strony. Aby to wykonać, należy zaimplementować w klasie tegoż systemu interfejs ioptPagesystem, wrzucić jego obiekt do parsera i zastosować instrukcję {pagesystem}. Podobnie, jak w wypadku drzew, definiujemy tu wygląd poszczególnych elementów w postaci nowych znaczników. Możemy je także utworzyć raz za pom. bindGroup i później ładować je w miarę potrzeby znacznikiem {use snippet="nazwa"/}. Oto przykład:
{pagesystem=ps} {page}[ <a href="{@url}">{@title}</a> ]{/page} {active}< <strong><a href="{@url}">{@title}</a></strong> >{/active} {separator}...{/separator} {next}<a href="{@url}"><<</a>{/next} {prev}<a href="{@url}">>></a>{/prev} {/pagesystem}
Wracając jeszcze do sekcji... nie wiem, czy ktoś tego używał, ale w dotychczasowych wersjach w trybie kompatybilności z XML-em dostępny był ogranicznik w postaci atrybutu XML: opt:put="tresc". Jego zniknięcie jest jedyną niekompatybilnością wstecz, ponieważ jego miejsce zajmują tzw. atrybuty OPT, za pomocą których można robić różne ciekawe bajery. Oto, jak teraz wykonywane będzie naprzemienne kolorowanie elementów tabeli, robione dotąd funkcją cycle() na wzór Smarty:
<table> <tr> <td>Product name</td> <td>Product Price</td> </tr> {section=products} {cycle='class'; 'brighter'; 'darker'} <tr> <td opt:sectioncycle="products">{$products.name}</td> <td opt:sectioncycle="products">{$products.price}</td> </tr> {/section} </table>
Jeszcze tylko trzeba tu wymyślić jakiś elegancki sposób na wykorzystywanie raz zdefiniowanych wzorów cykli w wielu miejscach, ale idea pozostanie, jak powyżej. Atrybut opt:sectioncycle zostanie zastąpiony atrybutem class z wartością naprzemiennie: "brighter", "darker".
Jak się Wam podobają nowe możliwości?







Napisał Diablos w piątek, 1 grudnia 2006 o 22:29
Nowe mozliwosci sa ok, ale musze przyznac ze sa zbedne. Na pewno wiekszosc programistów wykorzystujacych OPT radzila sobie doskonale mimo braków wyzej wymienionych.
Nie smiem kwestionowac Twoich priorytetów, ale przykladowo mojej osobie wieksza radosc sprawiłby tytuł "OPP 0.1" czy tez "OPS 0.1", a nawet "OPD 0.5".
OPT miał być przeciez podprojektem, a narazie rozwija sie zupelnie nieproporcjonalnie do innych (tak mi sie wydaje).
Szczerze powiedziawszy myslalem, ze wraz z wydaniem wersji finalnej 1.0 pojawi sie w Twoim grafiku czas na rozwijanie innych podprojektów, mniej uwagi bedzie poswiacanej OPT... mniej tzn. tylko na poprawe bledów.
Tak czy siak, dobra robota, pozdrawiam.