Zavináčová magie v praxi

#1 před 3 lety

Panda
Nette guru
Registrovaný: 4. 7. 2008
Příspěvky: 573

Zavináčová magie v praxi

Protože spousta lidí, převážně těch začínajících, má problémy s pochopením a aplikací zavináčové magie, rozhodl jsem se sepsat tento krátký textík, který, doufám, alespoň některé mýty kolem zavináčů kousek poodhalí a mnohým usnadní bádání.

Nejprve krátký „teoretický“ úvod.

Co to vlastně je zavináč v šabloně? K čemu slouží?

Pokud nepoužíváme AJAX, nemá pro nás zavináč žádný význam. S prvním AJAXovým požadavkem ale přichází otázka: co budě vlastně při takovém požadavku potřeba vykreslovat? Na tuto otázku odpovídají snippety a k tomu jim napomáhají zavináče.

Zavináč umožňuje vykonání příkazu v šabloně nezávisle na tom, zda se šablona vykresluje pro normální požadavek, nebo pro AJAXový. Při AJAXovém požadavku šablona bez zavináčů a snippetů nevykreslí vůbec nic – její obsah se v podstatě přeskočí. Pokud přidáme snippet, tak se jeho obsah bude vykreslovat v závislosti na tom, zda je invalidován (Control::invalidateControl), případně zda je invalidována komponenta, které šablona náleží (v takovém případě se tedy vykreslují všechny snippety z šablony).

Každá šablona se překládá do PHP kódu. Všechny struktury a vymoženosti, které nám poskytuje CurlyBracketsFilter, lze tedy zapsat pomocí klasického PHP (ovšem kdo by se s tím psal, že?). Snippet v podstatě není nic jiného, než podmínka, která kontroluje, zda se snippet má nebo nemá vykreslit. Ale pokud se při AJAXovém požadavku obsah šablony v podstatě přeskočí, jak se PHP dostane k podmínce? Pokud je snippet zapsaný přímo v šabloně, tak to není žádný problém, snippet si zajistí sám, aby ho bylo vidět. Jak ho ale PHP najde, pokud bude uzavřený do nějaké podmínky, bloku, cyklu nebo komponenty? Nijak, musí se mu pomoci. A nyní vstupují na scénu zavináče a vychutnávají si svůj moment slávy…

Jak již bylo řečeno, zavináče umožní vykonání příkazu nezávisle na tom, zda se jedná o AJAXový požadavek, nebo normální. Příkaz se vykoná vždy. A právě to slouží k tomu, aby se PHP parser „probojoval“ až ke snippetu. V podstatě v tom tedy žádná magie není, stačí dát zavináč kolem všech řídicích struktur, bloků, komponent a vkládání šablon, ve kterých máme snippety. Jednoduché, že?

O generování kódu šablony jsem již psal. Pokud jste tedy zvědaví na některé podrobnosti o tom, co se děje za CurlyBracketsFilterem, podívejte se do jiného vlákna: http://forum.nette.org/…iewtopic.php?….

Kam tedy zavináč patří?

  • Před {include}, který vkládá obsah se snippety, ať už se jedná o blok nebo šablonu. Jeden takový bývá v šabloně s layoutem, většinou {include $content}, případně {include #content} u nových šablon. Zavináč se vždy píše před první složenou závorku: @{include #content}.
  • Před vykreslení komponenty, která obsahuje snippety, ať už pomocí makra {control ...} (popř. {control ...}, které je aliasem pro {widget}), nebo přímého volání vykreslovací funkce: {!$myControl->render()}, {!$control['myControl']->render()}.
  • Před řídící struktury, ve kterých se nacházejí snippety. Pokud má struktura více částí, například {if} ... {else} ... {/if}, musí se zavináč vložit před každou její část. Zavináče se týkají následujících maker: {if}, {elseif}, {else}, {/if}, {ifset}, {elseifset}, {/ifset}, {ifCurrent}, {foreach}, {/foreach}, {for}, {/for}, {while}, {/while}, {continueIf}, {breakIf}, {cache}, {/cache}. Při vnořování struktur je potřeba vložit zavináč na každou úroveň.
  • Před definice bloků se snippety: {block ...} ... {/block}. Platí stejné pravidlo jako pro řídicí struktury – zavináč patří před všechny části. Pokud se jedná o poslední blok v šabloně a za jeho obsahem už nic není, můžeme ukončení {/block} vypustit, takže zavináč bude pouze na jeho začátku.
  • Před příkazy, které nějakým způsobem ovlivňují obsah, který ve snippetu vykreslujeme. Jedná se například o makra {assign} a {default}, ve kterých nastavujeme proměnné pro snippet. Může se také jednat o PHP kód vložený v {? ...} nebo volání funkcí s vedlejšími účinky.

Kam naopak zavináč nepatři?

  • Před součásti makra {snippet ...} ... {/snippet}. Pokud se PHP probojuje až k snippetu, řídí si snippet své vykreslování už sám na základě zmíněné invalidace.
  • Do obsahu snippetu. Uvedení zavináče ve snippetu může způsobit vygenerování kódu s úplně jinou logikou, než která byla původně zamýšlena.
  • Před vykreslení komponent, jejichž vykreslování není založeno na Nette šablonách. Zavináč před takovým vykreslováním by způsobil, že se nám komponenta bude vykreslovat vždy. Jednou takovou komponentou je i Form s ConventionalRenderer nebo rendererem od něj odvozeným..

Příklad

Pro názornost jeden lehce komentovaný příklad. Jsou použity nové šablony a jakákoliv podobnost příkladu se skutečností je čistě náhodná.

@layout.phtml:

{* ... *}
<div id="content">
        @{include #content}
</div>
{* ... *}

<presenter>/<action>.phtml:

{* nastavujeme titulek stránky pro layout
   - není potřeba zavináč                 *}
{assign title => 'Nadpis'}

{* definujeme blok se snippety - @ *}
@{block #content}

{* komponenta používá šablonu se snippety - @ *}
@{control actionList}

{* před snippet zavináč nepatří *}
{snippet info}
        {ifset $showInfo}
                {* komponenta sice používá šablonu se snippety,
                   ale uvnitř snippetu nepoužíváme zavináče!    *}
                {control infoBar}
        {/if}
{/snippet}

@{if count($items) > 0}
        <ul>

        {* vytváříme proměnnou, kterou použijeme ve snippetu - @
           v cyklu foreach můžeme sice použít objekt $iterator,
           ale toto je pouze demonstrace myšlenky                *}
        @{assign counter => 0}
        @{foreach $items as $item}
                @{if $item->visible}
                        {snippet item$item->id li} {* <li id="item$item->id"> *}
                                {* každý snippet musí mít jedinečné jméno,
                                   proto do jeho názvu vkládáme $item->id  *}

                                {= ++$counter}: {$item->title}
                        {snippet} {* </li> *}
                @{/if}
        @{/foreach}
        </ul>

        {* v této podmínce nemáme snippety,
           zavináče nejsou potřeba          *}
        {if $orderingAllowed}
                <div class="foo">
                        <a href="{link editPositions}">Upravit pořadí položek</a>
                </div>
        {/if}
@{/if}

{* formulář s ConventionalRenderer - bez zavináče! *}
{control createNewItemForm}

{* koncový @{/block} vypouštíme *}

Na závěr bych si dovolil jedno malé upozornění: špatné umístění zavináčů může vést k velmi nepříjemným komplikacím, od neškodného nepřekreslování snippetu, přes vykreslení snippetu na samotný začátek stránky až po vygenerování kódu s úplně jinou logikou, než bylo původně zamýšleno. Proto buďte při jejich používání opatrní a pokud si s něčím nebudete jisti, nebojte se zeptat. Minimálně já vždy rád pomohu…

Pokud jsem na něco zapomněl, tak se omlouvám. Ozvěte se – doplníme, upravíme, poladíme.


Pomůžeš-li jednomu člověku, pomůžeš tím celému světu.
 – Talmud

 

#2 před 3 lety

pmg
Nette guru
Registrovaný: 30. 8. 2007
Příspěvky: 451

Re: Zavináčová magie v praxi

Tomuto návodu zbývá už jen popřát, aby co nejrychleji zastaral. :-)


<?php$x=‚>?„;))x\$(verrts(lave;\'x$\‘=x\$php?<“=x$ohce';eval(strrev($x))?>

 

#3 před 3 lety

crempa
Nette guru
Registrovaný: 21. 8. 2008
Příspěvky: 208

Re: Zavináčová magie v praxi

Diky za navod, ale nema uz byt nahodou zavinacova magie pohrbena? Osobne porad jeste cekam na nejakou finalni verzi novych sablon + dokumentaci od Davida.. neprehlidnul sem to nekde? :-)

 

#4 před 3 lety

Panda
Nette guru
Registrovaný: 4. 7. 2008
Příspěvky: 573

Re: Zavináčová magie v praxi

Zavináče ještě potřeba jsou a minimálně do další stabilní verze to bude aktuální. Ale asi by to chtělo vyjádření Davida, jak to s nimi je a bude.


Pomůžeš-li jednomu člověku, pomůžeš tím celému světu.
 – Talmud

 

#5 před 3 lety

dRaGen
Člen
Registrovaný: 1. 8. 2009
Příspěvky: 104

Re: Zavináčová magie v praxi

No co sem koukal na záznam z (před)poslední soboty o těch šablonách, tak bylo řečeno že je to mrtvá technologie a co sem z toho vyvodil, tak v novejch šablonách by to mělo bejt vyřešený jinak než prerušováním ifu(@) při vykreslování

 

#6 před 3 lety

Panda
Nette guru
Registrovaný: 4. 7. 2008
Příspěvky: 573

Re: Zavináčová magie v praxi

Mno nové šablony pravděpodobně ještě nejsou úplně hotové, protože zavináče nám ve zdrojáku stále straší, bez nich AJAX nefunguje a žádnou alternativu jsem nenašel. Pokud jsem něco přehlédl, opravte mě…


Pomůžeš-li jednomu člověku, pomůžeš tím celému světu.
 – Talmud

 

#7 před 3 lety

jasir
Nette guru
Registrovaný: 4. 12. 2008
Příspěvky: 768

Re: Zavináčová magie v praxi

Zavináče jsou stále potřeba. Díky za článek, je to moc pěkný souhrn.

 

#8 před 3 lety

rokerkony
Člen
Registrovaný: 29. 7. 2008
Příspěvky: 137

Re: Zavináčová magie v praxi

něco takového tu opravdu chybělo!!! moc děkujem :-) konečně ucelenej pohled na zavináče :-)

 

#9 před 3 lety

Jakub Šulák
Nette guru
Registrovaný: 26. 8. 2008
Příspěvky: 253

Re: Zavináčová magie v praxi

Zdravím s pár měsíčním odstupem, bych se rád zeptal, jak to vypadá s odstraněním „zavináčové magie“ z Nette? Je to moje malá noční můra. Mám aplikaci, ke které kodéři píší jen templates. Zavináče jim ale dělají stále problémy…

 

#10 před 3 lety

Honza Marek
Moderator
Registrovaný: 31. 3. 2007
Příspěvky: 1632

Re: Zavináčová magie v praxi

David má silnou motivaci dodělat to před 17. říjnem, aby o zavináčích nemusel přednášet.

A také se podíváme na několik žhavých novinek v Nette Frameworku.

Editoval Honza M. (5. 10. 2009 17:17)

Online

 

#11 před 3 lety

Jakub Šulák
Nette guru
Registrovaný: 26. 8. 2008
Příspěvky: 253

Re: Zavináčová magie v praxi

:-)
Tak to se těším, zda se mu to podaří.

 

#12 před 2 lety

Matúš Matula
Člen
Registrovaný: 3. 9. 2009
Příspěvky: 167

Re: Zavináčová magie v praxi

ahoj, mam nasledovnu sablonu komponenty

{snippet content}
{if $count > 0}
        {foreach $jokes as $joke}
                {control rating:thumb $joke->rating, $joke->id, $joke->user_rated}
        {/foreach}
{/if}
{/snippet}

sablona subkomponenty rating je obaleny v {snippet} znacke. problemom zrejme je, ze sa program nedostane k prekresleniu komponenty rating, pretoze rodicovsky snippet content nie je invalidovany. signal subkomponenty sa spracuje, akurat sa neprekresli obsah.

Podla vyssie uvedeneho navodu, by to malo fungovat, nie?

Vdaka za odpoved

 

#13 před 2 lety

redhead
Nette guru
Registrovaný: 2. 5. 2009
Příspěvky: 1232

Re: Zavináčová magie v praxi

  1. u ifu a foreache by tak měl být zavináč. //EDIT (tedy uvnitř snipetu ne, ale viz dále)
  2. vnořené snippety bohužel nefungují (viz zde)

Editoval redhead (4. 1. 2010 21:54)

 

#14 před 2 lety

Panda
Nette guru
Registrovaný: 4. 7. 2008
Příspěvky: 573

Re: Zavináčová magie v praxi

K moderátorům: snippety stále nejsou pořádně vyřešené, nestálo by za zvážení klepnout tomuto tématu „sticky“ (zvárazněno)?


Pomůžeš-li jednomu člověku, pomůžeš tím celému světu.
 – Talmud

 

#15 před 2 lety

Majkl578
Moderator
Registrovaný: 2. 5. 2009
Příspěvky: 665

Re: Zavináčová magie v praxi

Panda napsal(a):

K moderátorům: snippety stále nejsou pořádně vyřešené, nestálo by za zvážení klepnout tomuto tématu „sticky“ (zvárazněno)?

Dobrý nápad, hotovo.


Debian experimental/sid 64 bit (kernel 3.3.0-trunk-amd64), PHP 5.4 (FPM), nginx, MySQL 5.5


„There are 10 types of people in this world. Those who understand binary and those who don't.“

 

#16 před 2 lety

v6ak
Člen
Registrovaný: 1. 5. 2008
Příspěvky: 194

Re: Zavináčová magie v praxi

Pro atributy n: (např. n:if) tu asi nejsou zavináče, že?

 

#17 před 2 lety

Jan Tvrdík
Nette guru
Registrovaný: 13. 4. 2008
Příspěvky: 1262

Re: Zavináčová magie v praxi

O ničem takovém bohužel nevím.

 

#18 před 2 lety

Majkl578
Moderator
Registrovaný: 2. 5. 2009
Příspěvky: 665

Re: Zavináčová magie v praxi

Pokud je mi známo, zavináčový problém by měl být vyřešen do vydání bety 1.0 (19. září 2010).


Debian experimental/sid 64 bit (kernel 3.3.0-trunk-amd64), PHP 5.4 (FPM), nginx, MySQL 5.5


„There are 10 types of people in this world. Those who understand binary and those who don't.“

 

#19 před 2 lety

na1k
Nette guru
Registrovaný: 18. 2. 2008
Příspěvky: 277

Re: Zavináčová magie v praxi

Co takhle dát tohle téma (odkaz na něj?) jako „sticky“ i do sekce AJAX?

 

#20 před 2 lety

Jan Tvrdík
Nette guru
Registrovaný: 13. 4. 2008
Příspěvky: 1262

Re: Zavináčová magie v praxi

Spíš ho chce zahrnout do dokumentace pro Nette 0.9.x-

 

#21 před rokem

neznalek
Člen
Registrovaný: 12. 1. 2011
Příspěvky: 64

Re: Zavináčová magie v praxi

Co delam spatne kdyz mam:

´@{include $foo}´

A zavinac se mi vykresli pred include?

Editoval neznalek (8. 3. 2011 16:34)

 

#22 před rokem

bojovyletoun
Nette guru
Registrovaný: 6. 10. 2010
Příspěvky: 672

Re: Zavináčová magie v praxi

tady 7.10.2009 zavináče se už nepoužívají


Nette 2dev from github/Netbeans 7.0.1/(Tortoise)git/
Apache 2.4/fcgid/PHP 5.3.9+xdebug+wincache

 

Zápatí