Autor Zpráva
Pavel Straka
Profil
Dobrý večer, rád bych požádal o radu zkušenějších.
Pokouším se vytvořit jednoduchý šablonový systém. Jako základ jsem použil to, co popisuje Alphard zde: php šablona
Nyní by mě zajímala možnost, jak bych toto mohl elegantně rozšířit tak, abych měl vyřešený případ, kdy potřebuji vypsat z databáze několik řádků a zároveň měl možnost editovat podobu tohoto výpisu v šabloně. Pokusím se to ještě příbližit na příkladu. Řekněme, že mám v databázi tabulku o 3 sloupcích (a,b,c) a chci vypsat všechny řádky tabulky.
Takto bych to řešil klasicky bez "šablonovacího systému:
$dotaz = MySQL_Query("SELECT * FROM tabulka");
while ($r = MySQL_Fetch_Array($dotaz)) {
  echo "<div class='a'>".$r["a"]."</div><div class='b'>".$r["b"]."</div><div class='c'>".$r["c"]."</div>";
}

Existuje způsob, jak šabloně předat jednoduše proměnné a ostatní záležitosti (v tomto příkladu tagy <div>) řešit až v šabloně?
Děkuji věem za pomoc.
Alphard
Profil
Pavel Straka:
V podstatě potřebujete cyklus na úrovni šablony. "Velká řešení" kompilují šablony do PHP kódu, ten cachují a není problém tam čarovat s libovolnými výpisem.
To, co jsem představil v odkázaném vlákně, je spíš principiální základ založený na nahrazování řetězců a není rozumně rozšiřitelný tímto směrem.

Určitá možnost je udělat blok šablony, vyrenderovat ho a ten pak vložit do další šablony. Ale je jasné, že to není ono.

<?php
include "template.php";

$buffer = '';
while ($r = MySQL_Fetch_Array($dotaz)) {
  $buffer .= insertTemplate('blokVypisu.html', $r);
}
 
$t = array();
$t['nadpis'] = "Jednoduchý templatovací systém";
$t['autor'] = "Alphard";
$t['clanky'] = $buffer;
$t['obsah'] = 'Ukázka, jak by mohl vypadat jednoduchý templatovací systém s použitím funkce <a href="http://cz.php.net/manual/en/function.str-replace.php">str_replace()</a>.';
 
$h = array();
$h['title'] = "Template system";
 
echo insertTemplate('head.html', $h);
echo insertTemplate('clanek.html', $t);
echo insertTemplate('foot.html');


Další vývojový krok by mohlo být trochu složitější parsování šablony, kde nebude jen primitivní replace, ale budou se třeba i volat nějaké callbacky.
Nebo hned přeskočit na kompilované šablony jako Latte, Smarty apod.
Pavel Straka
Profil
Máte pravdu, že ten blok šablony - to není ono, také mě toto řešení, jako poslední možnost, napadlo.
Mohl byste být prosím tak laskav a trochu mi přiblížit řešení s cyklem na úrovni šablony, a to, co jste psal o kompilaci šablon do PHP kódu?
O Latte, Smarty apod. nemám zájem, rád bych měl k dispozici co nejjednodušší systém.
Děkuji Vám za ochotu.
Keeehi
Profil
Latte je právě to kompilování šablon do PHP kódu. Koukněte, jak to funguje tam a pak si můžete vytvořit svůj jednodušší systém.
Alphard
Profil
Pavel Straka:
Napadla mě ještě možnost upravit funkci insertTemplate tak, že místo proměnné by šlo předat pole a k tomu druhá šablona, popř. blok šablony definovat v kódu. Implementace není tak složitá, můžu se o to pokusit, ale určitě ne dneska.
Jenže lidé, kteří mají zkušenosti s větším systémem ví, kam tohle povede. Za chvíli budou potřeba podmínky, pak další funkce jako zkrácení textu, odstranění nějaký znaků, escapování celkově, empty()...

Takže se nabízí otázka proč ne Latte? Viděl jste ho? Co se vám nelíbí na velkém řešení? Bojíte se o výkon, nechcete se ho učit, máte problém ho implementovat, chcete mít vše vlastní?
Ugo
Profil
Pavel Straka:
mám vlastní šablony, miluji je ale vždy budu vědět že síly a otestovanosti třeba toho Latte nedosáhnout. Smarty bych nedoporučil ani nepříteli, i když poslední verze už vypadají použitelně. Rozhodně chápu vaší touhu mít to po svém, ale počítejte s tím že se to zkomplikuje, bohužel třeba já nepřišel na to jak využít latte z nette samostatně a když jsem se pokoušel nahrazovat závislé funkce (které dělají to samé co nativní funkce) tak sem to v půlce vzdal jak jich bylo hodně .. navíc problém s legitimností takového použití (minimálně morální) :) Tak mé řešení nevložím, nevejde se do délky příspěvku, což je asi dobře
Kcko
Profil
Ugo:
Já jsem to zkoušel a nic to není. Jen je holt potřeba mít osekaný adresář Nette, kde Latte potřebuje ke svému životu ještě několik dalších knihovniček.
Latté jsem zavrhl, nějak jsem potřeboval udělat jednodušší projekt a nebavilo mě neustále koukat do dokumentace a pořád studovat jak zapsat tohle a jak tohle.

Takže mám vlastní MVC kde v šabloně je jen jednoduché PHP určené k výpisu dat. K Latte se možná časem vrátím.
Pavel Straka
Profil
Byl jsem celý den pryč, takže se se svým příspěvkem k tématu přidávám až teď.
Keehi: Podívám se na to. Mám pocit, že už jsem něco podobného viděl, jen si už nemůžu vzpomenout kde. Bylo to nějaké opensource řešení e-shopu.
Alphard: Mohl byste prosím být tak hodný a rozvést tu myšlenku s tím cyklem na úrovni šablony? Nebo to je právě to, co najdu v Latte?
Proč se mu chci vyhýbat vlastně sám pořádně nevím. Nejlepší vysvětlení je asi to, že mám pocit, že pro moje potřeby stačí naprostý základ - vyřešit jen tuto záležitost a použití rozsáhlejšího systému je zbytečné a nepřehledné.
Ugo: Mohl byste prosím i Vy být tak laskavý a poradit mi, jak jste ve svém vlastním systému vyřešil podobnou záležitost?
Děkuji všem.
Alphard
Profil
[#8] Pavel Straka
Nejste první, kdo se zajímá o nějaké primitivní šablony, zkusím updatovat ten starý návrh (zítra mu budou přesně dva roky), ale nemohu slíbit žádný termín.
Pokud jde o Latte, výhoda kompilovaných šablon je také v tom, že jejich rozsáhlé schopnosti neubírají výkon, když nejsou použity. Možná zkusím dát dohromady nějaký jednoduchý příklad, jak je začlenit od již existujícího systému.

[#7] Kcko
To slyším často, ale moc to nechápu. Latte automaticky escapuje, je tam dědičnost šablon, každou chvíli člověk potřebuje |truncate:40, |number:2:',':' ', |date:'...', {if $iterator->isOdd()}, {if $iterator->isFirst()}, n:if="$a->count>1"
To fakt radši všechno píšeš sám?
Pavel Straka
Profil
To byste byl moc hodný. Myslel jsem, že to bude primitivní, že to bude vyřešené za jeden večer. Když nejsem první, kdo se shání po jednoduchých šablonách, jak to, že nemohu nic podobného najít? Vážně jsem myslel, že to bude maličkost. :)
Kcko
Profil
Alphard:
Mám v PHPEdu nějaké snippety a píšu celkem rychle (500 úh / min), takže mi to problém ani nedělá.
Větší problém mi dělalo v nějaké šabloně vypsat cosi trošku složitěji, a po 20 min koukání do dokumentace Latté jsem to vzdal a udělal to sobě známým a rychlým způsobem.

|truncate:40  => Str::perex($str, 40)
{if $iterator->isOdd()}  => $i & 1
{if $iterator->isFirst()} => if ($counter == 1)
...

Vím, že to je horší na napsání a nevypadá to tak efektně, ale u mě nenastal čas, kdy mám nějakou dobu volno a chce se mi zrovna vrtat se v Latte. Píšu placený projekt => nemám čas studovat jak efektivněji časově i vzhledem napíši nějakou podmínku s iteratorem či separatorem hezčeji (Ani klient by to neocenil ;-]). Možná časem se k tomu opět vrátím, až se budu nudit a budu mít pocit, že je potřeba hnout se kupředu.

Co se týká dědičnosti šablon, nijakou extra krásu sem v tom neviděl, mám vlastní MVC kdy jeden controler může obsahovat více šablon poskládaných do sebe nebo se to zavolá jako pole modulů a nemám tedy Latté potřebu, chce to čas, i k DIBI jsem se chvíli prokousával ;]
Pavel Straka
Profil
Narazil jsem na stránku, kde pan Vrána popisuje další dva šablonovací systémy: "Oblíbil jsem si proto spíše HTMLTmpl, který podle mě umožňuje přesně to, co by umožňovat měl – nic míň a hlavně nic víc. V Česku je oblíbený také Teng původně vyvinutý Seznamem."
http://php.vrana.cz/sablony.php

Myslíte si, že jsou opravdu jednodušší než Latte? Máte s tím zkušenosti? Děkuji.
Kcko
Profil
Jinak ještě k tématu: Jak se Pavlovi nelíbí, nebo ne zcela vyhovuje vnořování šablon do sebe #2, řádek 6, tak by se to dalo řešit jednou šablonou, kde část kde je výpis v cyklu, by byl 1 řádek v "bloku" ve smyslu

<h1>{$title}</h1>
<table>
%BLOCK_USERS%
<tr><td>{$value}</td></tr>
%BLOCK_USERS%
</table>

Akorát by se zde pouze prostě nenahrazovaly proměnné, ale ty bloky by se musely regulárním výrazem nejdřív vyzobat a poté vyplnit dynamickou hodnotu (polem např.)

Systém RS2 od Juneau to tak myslím měl, nějak tak podobně ...
Alphard
Profil
[#11] Kcko
Tak je to určitě o zvyku, měl jsem se zeptat na isLast(), ne na isFirst() :-). Osobně mně nejde o to, jestli to vypadá efektně, ale jak dobře nebo špatně se to píše. Prvně když David přidal n:bloky, tak se mi to moc nelíbilo, nebyl jsem na zvyklý. Ale časem člověk zjistí, že fakt je otrava psat ukončovací endif, endforeach... apod.

Jak uvádíš ty bloky, podobnou jsem měl představu pro úpravu toho mého scriptu. Označit blok a pojmenovat ho. Pak se mezi jinými proměnnými předá pole, kde se hodnoty ve vnitřním asociativním poli nahradí za zástupné znaky. Jen k tomu chci dát ještě aspoň možnost podmínek.

[#12] Pavel Straka
Ten článek jsem kdysi dávno četl, je z roku 2005, od té doby se hodně změnilo, před sedmi lety vůbec Latte neexistovalo. V knize 1001 tipů a triků Jakub zmiňuje hlavně Latte, výjimečně Smarty (ale ještě jsem ji nestihl přečíst celou).
Osobně bych tato řešení ani moc nehledal. Když už se učit jinou syntaxi, tak něčeho používaného, ne projektu, který používá půl promile lidí. Jakub ještě někde zmiňoval trochu novější šablonovací systém, že se mu líbí, ale teď si na to nemohu vzpomenout. Ale nebylo tam nic, co by neumělo Latte.
Pavel Straka
Profil
Aha, rozumím, to mě nenapadlo, že ten článek nemusí být aktuální.
Rozumím Vám i jak to myslíte, s použitím frekventovanějšího systému.
Moje představa ale byla ta, že bych jen na základě Vaší rady/myšlenky, s Vaší pomocí rozšířil ten Váš základ jen o tuto možnost použití cyklů. Je moje představa opravdu tak naivní?
Kcko
Profil
Pavel Straka:
Ne není, a vy vůbec nevíte jak na to? Podívejte se na RS2 systém, na to parsování a třeba Vás něco napadne.
Pavel Straka
Profil
Přiznám se, že nemám žádnou představu. Potřeboval bych nějak nasměrovat.
Ugo
Profil
Pavel Straka:
Já to řešil právě tou kompilací, původně jsem chtěl možnost i bez ní, ale to je na mě moc. Ale kompilace je jednoduchá, de jenom o sérii regulárů a nahrazování za php kód, pak to uložíš a includneš. U mě k tomu je třída co to zparsuje (a zpracovává si cache) a třída která se stará o vykreslení. A výsledek je, že všechny moje pokusy udělat v tom něco nestandartního skončí parse errorem v šabloně :-D (ale vždy se najde řešení jak to obejít nebo opravit). Posílám zip s potřebným k nakouknutí jak neelegantně se nechá tohle řešit a přitom to fajčilo.
http://luci-project.org/render.zip
Pavel Straka
Profil
Děkuju za pomoc, ale nemůžu v tom najít to, co potřebuji.
Pokud tedy neexistuje jednodušší možnost, byl bych pro ten systém HTMLTmpl, který mi připadá nejprimitivnější.
http://htmltmpl.sourceforge.net/
Našel jsem k němu i českou dokumentaci: http://ondrej.jikos.cz/vyuka/swi117/2007/sablonovaci-system-htmltmpl.pdf
, ale přesto nejsem schopný dát dohromady kód, který by vypsal v šabloně několik řádků tabulky - jak jsem psal v prvním příspěvku, že bez šablony bych to řešil takto:
$dotaz = MySQL_Query("SELECT * FROM tabulka");
while ($r = MySQL_Fetch_Array($dotaz)) {
  echo "<div class='a'>".$r["a"]."</div><div class='b'>".$r["b"]."</div><div class='c'>".$r["c"]."</div>";
}
Nebyl by, prosím, někdo tak hodný, a nepomohl mi s tím?
Děkuji mnohokrát.
Pavel Straka
Profil
Vrátil jsem se k problému až teď a nyní už jsem pochopil, jak toto v tom šablonovacím systému HTMLTmpl vyřešit. Je to primitivní.
Takže děkuji všem za pomoc, zůstanu u tohoto systému.
Pavel Straka
Profil
Dobrý večer, rád bych ještě otevřel toto téma.

Zjistil jsem, že tento šablonovací systém neumí vypsat cyklus jako obsah jiného cyklu, což mně působí potíže zejména v případě, kdy dejme tomu, vypisuji data jednoho řádku tabulky.
To jsem dělal takto:
$dotaz = MySQL_Query("SELECT a,b,c FROM tabulka");
$radek = MySQL_Fetch_Array($dotaz);
$tproc->set("radek",$radek); 

A v šabloně jsem následně vypsal:
<TMPL_LOOP radek>
  <TMPL_VAR a>,<TMPL_VAR b>,<TMPL_VAR c>
</TMPL_LOOP>

Ale pokud bych chtěl nyní vypsat obsah jiného pole (ale stále uvnitř tohoto příkazu LOOP), není to možné. Jediná možnost je příkaz LOOP přerušit, vypsat co potřebuji a potom znovu spustit další příkaz LOOP. To mi ale přijde jako dost kostrbatý způsob.

Napadlo mě, že místo předávání hodnot v poli bych předával jednotlivé proměnné (jde přibližně o 10 hodnot/proměnných), ale jednak nevím, jak napsat takový kód, který by šabloně předaval jednotlivé proměnné (rozepíšu se níže) a za druhé nedokážu odhadnout, jak velký dopad by to mělo, co se týče rychlosti provádění skriptu.

Představoval jsem si že by kód pro předávání proměnných vypadal nějak takto:
$dotaz = MySQL_Query("SELECT a,b,c FROM tabulka");
... a nyní bych potřeboval získat jednak název sloupce a jednak jeho hodnotu a pak takto předat šabloně...
$tproc->set("nazev_sloupce","hodnota_sloupce"); 

Kód šablony by pak vypadal jednoduše takto:
  <TMPL_VAR a>,<TMPL_VAR b>,<TMPL_VAR c>

Děkuji všem za ochotu pomoci.


$dotaz = MySQL_Query("SELECT a,b,c FROM tabulka");
   $radek = MySQL_Fetch_Assoc($dotaz);
   
   foreach ($radek as $key=>$val) {
      $tproc->set($key,$val); 
   }

Myslím, že jsem vymyslel způsob. Zbývá tedy jen ta otázka systémové náročnosti.
Alphard
Profil
Zdravím, tak zaprvné, nemohu si nerýpnost, ale já jsem to říkal. Teď máte nedostatečně funkčí šablonovací systém, který navíc skoro nikdo nezná :-)

To znamená, že se šablonou neporadím, ale pokud jde o konkrétní dotaz
a nyní bych potřeboval získat jednak název sloupce a jednak jeho hodnotu a pak takto předat šabloně
tak po použití mysql_fetch_assoc() se snadno dostanete k názvu sloupců. (mysql_fetch_array() by šlo taky, ale ta funkce zbytečně spojuje ještě mysql_fetch_row()).
Vypište si print_r(mysql_fetch_assoc($dotaz)); a uvidíte.
Pavel Straka
Profil
Přiznám se, že jsem rýpnutí čekal. :) Ale pořád si stojím za tím, že pro mé potřeby je ten systém naprosto dostačující a vzhledem k jeho jednoduchosti ani nevadí, že ho podle Vás nikdo nezná (pro výpis proměnné je příkaz TMPL_VAR, pro cyklus TMPL_LOOP, podmínka TMPL_IF, jiný příkaz jsem nepoužil).

Ano ano, zřejmě jste psal odpověď dříve, než já jsem doplnil dodatek s MySQL_Fetch_Assoc. Mohl byste se, prosím, ještě vyjádřit k rozdílu v náročnosti vykonávání skriptu v případě použití tohoto způsobu? Děkuji Vám.
Alphard
Profil
Systémová náročnost bezproblémová. Mnoho knihoven dělá daleko větší úpravy s daty a o ORM systémech ani nemluvím. Server by to neměl ani poznat, jestli to nezpracovává tisíce řádků.
Pavel Straka
Profil
Výborně, děkuji Vám za pomoc.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: