Latte 3 {php malformed content
- Čamo
- Člen | 798
Ahoj,
vie mi niekto prosím vás poradiť prečo mi šablona vyhadzuje error keď
chcem použiť {php} makro?
Error je
Latte\CompileException
Malformed tag contents in
…\DevicesPlaylist\playlist_information.latte:78
Kód vyzerá takto
{php
$accessCssClass = 'btn-danger';
$accessText = '';
if ( $last_access ) {
$now = new \DateTime();
$to_time = strtotime($last_access->format('d.m.Y H:i:s'));
$from_time = strtotime($now->format('d.m.Y H:i:s'));
$minute = round(abs($to_time - $from_time) / 60, 2);
if ($minute <= 20) {
$accessCssClass = 'btn-success';
$accessText = $presenter->translate("device.online", "Online");
}
else {
$accessCssClass = 'btn-warning';
$accessText = $presenter->translate("device.offline", "Offline");
}
}
else {
$accessText = $presenter->translate("device.never_connected", "Never connected");
}
}
Problém je až v tej vnútornej if else podmienke. Ale ja tam problém nevidím.
Editoval Čamo (26. 9. 14:15)
- Čamo
- Člen | 798
Ja toto makro bežne používam týmto spôsobom a normálne to funguje. Aj
pár riadkov nad týmto kódom.
Keď to použijem ako {php}{/php} tak mi to vyhodí error
Missing arguments in {php} in
…\DevicesPlaylist\playlist_information.latte:78
Dokumentácia ku tomu nieje žiadna :(
Editoval Čamo (26. 9. 14:41)
- Marek Bartoš
- Nette Blogger | 1260
To makro nikdy nepodporovalo syntaxi php neomezeně, stejně jako celé Latte. Nehodí se to pro velké bloky kódu
- nightfish
- Člen | 516
@Čamo
Když už jdu kolem, dovolím si pár nesouvisejících komentářů
k tvému kódu.
Část
$now = new \DateTime();
$to_time = strtotime($last_access->format('d.m.Y H:i:s'));
$from_time = strtotime($now->format('d.m.Y H:i:s'));
$minute = round(abs($to_time - $from_time) / 60, 2);
se dá napsat na jeden řádek třeba jako
$minute = round(abs((int) $last_access->format('U') - (int) (new \DateTimeImmutable())->format('U')) / 60, 2);
(aneb když máš DateTimeInterface
, je zbytečné jej
převádět na string v divném formátu a z něj zpětně vyrábět unixový
timestamp).
A pokud to pak jen porovnáváš s číslem 20 (a nikde vypočtenou hodnotu
nevypisuješ), tak ani to zaokrouhlení není potřeba.
Každopádně tohle je přesně typ kódu, který v šabloně nechceš řešit, protože v presenteru:
- si (aktuální) čas získáš přes službu z DI kontejneru místo
„netestovatelného“
new \DateTime()
- hodnotu 20 uložíš do nějaké rozumně pojmenované konstanty (např.
LAST_ACCESS_THRESHOLD_MINUTES
, případně „po novu“LastAccessThresholdMinutes
) a nebudeš mít pak v kódu magické číslo 20 - PHPStorm (či jiné IDE) ti pak snadno ukáže, že řádek
$accessText = '';
je zcela zbytečný
- m.brecher
- Generous Backer | 863
@Čamo
Když už @nightfish odbočil k tématu kvality kódu, tak já bych doplnil poznámku k architektuře kódu.
Problém který řešíš v šabloně v bloku makra {php} se vyskytuje často – převést nějaký stav business logiky do vizuální podoby. Já se v takovém případě snažím:
- oddělit business logiku od konkrétní vizuální podoby
- vizuální podobu (css třídy, textové popisky) mít v šabloně
- business logiku mít reprezentovanou stavovými parametry – boolean/enum
- business logiku mít v modelové třídě (domain model – pattern)
- alternativně mít business logiku v presenteru (anemický model – antipattern) – malé weby
Makro {php} by se mělo používat jen vyjímečně a podobné případy jako řešíš Ty rozčlenit jak je popsáno výše a v šabloně nastavovat css/texty v tagu {var} který je pro to i navržen.
Tvoje tlačítka mají 3 stavy, které by mohl reprezentovat např. bool parametr $isDeviceOnline – true|false|null
V šabloně převedeš stavový parametr na vizuální podobu:
{var
$buttonCss = match($isDeviceOnline){
true => 'btn-success',
false => 'btn-warning',
null => '',
},
$buttonCaption = match($isDeviceOnline){
true => 'device.online',
false => 'device.offline',
null => 'device.never_connected',
}
}
A business logika, kterou máš v bloku {php} se zapouzdří do metody modelové třídy:
class DeviceModel
{
public const int LastAccessThresholdMinutes = 20;
public function isOnline(): bool|null
{
//.....
}
}
presenter už pak jenom předá business logiku do šablony:
$this->getTemplate->isDeviceOnline = $this->deviceModel->isOnline();
Je to nepatrně více kódu, ale správně strukturované a přehledné. Anemický model (model bez business logiky) se v Nette aplikacích používá celkem často a použít se samozřejmě dá – ideálně v úplně jednoduchých aplikacích. Jakmile jde složitost aplikace nahoru, tak se 100% vyplatí doménový model, kde je business logika v modelu.
Sám správně píšeš:
Ja som to chcel dostať do šablony lebo celý ten kód sa týka zafarbenia buttonov. Nepáčilo sa mi že to bolo v presenteri. Tak som to zjednodušil a časť mám v presenteri a čast v šablone.
Přesně tak. Vizuální stránka business logiky má být v šabloně, zatímco business logika samotná v modelu. Presenter je potom čistý a soustředí se na řízení – tj. podobně jako controller ve standardním MVC modelu.