{"elements":[{"id":7007,"title":"Template Engine","body":"<section class=\"da-section\">\n  <div class=\"container\">\n    <h2>Sintassi Template<\/h2>\n    <p class=\"lead\">Il template engine di DressAPI permette di costruire interfacce HTML dinamiche attraverso una sintassi intuitiva, integrata nei file <code>.tmpl.php<\/code>. Gestito dalla classe <code>CHtmlRender<\/code>, supporta placeholder, cicli, condizioni, componenti riutilizzabili e traduzione automatica del testo.<\/p>\n\n    <h3 class=\"mt-4\">Variabili<\/h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Sintassi<\/th><th>Funzione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>&#123;&#123; variabile &#125;&#125;<\/code><\/td><td>Sostituzione variabile (escaped)<\/td><\/tr>\n          <tr><td><code>&#123;&#123; locals::variabile &#125;&#125;<\/code><\/td><td>Variabile locale del template<\/td><\/tr>\n          <tr><td><code>&#123;&#123; 'testo traducibile' &#125;&#125;<\/code><\/td><td>Testo con traduzione automatica via <code>_T()<\/code><\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n\n    <h3 class=\"mt-5\">Accesso ai dati annidati<\/h3>\n    <p>Usa <code>::<\/code> come separatore per accedere a dati annidati e indici di array:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template<\/div>\n<code>&#123;&#123; user::name &#125;&#125;\n&#123;&#123; user::details::email &#125;&#125;\n&#123;&#123; products::0::name &#125;&#125;<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Condizioni<\/h3>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;if(user::logged_in)]\n  &lt;p&gt;Benvenuto, &#123;&#123; user::name &#125;&#125;!&lt;\/p&gt;\n&#91;else]\n  &lt;p&gt;Effettua il login.&lt;\/p&gt;\n&#91;\/if]<\/code>\n    <\/div>\n    <p class=\"mt-2\">Operatori supportati: <code>==<\/code>, <code>!=<\/code>, <code>&gt;<\/code>, <code>&lt;<\/code>, <code>&gt;=<\/code>, <code>&lt;=<\/code>, <code>&amp;&amp;<\/code> \/ <code>and<\/code>, <code>||<\/code> \/ <code>or<\/code>, <code>!<\/code> \/ <code>not<\/code><\/p>\n\n    <h3 class=\"mt-5\">Blocchi condizionali: if-exists \/ if-not-exists<\/h3>\n    <p>Verifica se una variabile esiste e non &egrave; vuota:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;if-exists(user::avatar)]\n  &lt;img src=\"&#123;&#123; user::avatar | raw &#125;&#125;\" alt=\"Avatar\"&gt;\n&#91;\/if-exists]\n\n&#91;if-not-exists(user::bio)]\n  &lt;p&gt;Nessuna biografia disponibile.&lt;\/p&gt;\n&#91;\/if-not-exists]\n\n&#91;if-exists(product::discount)]\n  &lt;span class=\"badge\"&gt;Sconto &#123;&#123; product::discount &#125;&#125;%&lt;\/span&gt;\n&#91;else]\n  &lt;span class=\"badge\"&gt;Prezzo pieno&lt;\/span&gt;\n&#91;\/if-exists]<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Cicli (foreach)<\/h3>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;foreach from=\"products\" item=\"product\"]\n  &lt;div class=\"product\"&gt;\n    &lt;h3&gt;&#123;&#123; product::name &#125;&#125;&lt;\/h3&gt;\n    &lt;p&gt;&#123;&#123; product::price | number_format:'&euro;%.2f' &#125;&#125;&lt;\/p&gt;\n  &lt;\/div&gt;\n&#91;\/foreach]<\/code>\n    <\/div>\n    <h4 class=\"mt-3\">Foreach con chiave<\/h4>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;foreach from=\"settings\" item=\"value\" key=\"setting_name\"]\n  &lt;div&gt;&#123;&#123; setting_name &#125;&#125;: &#123;&#123; value &#125;&#125;&lt;\/div&gt;\n&#91;\/foreach]<\/code>\n    <\/div>\n    <h4 class=\"mt-3\">Variabili del loop<\/h4>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Variabile<\/th><th>Descrizione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>loop::index<\/code><\/td><td>Indice corrente (0-based)<\/td><\/tr>\n          <tr><td><code>loop::index1<\/code><\/td><td>Indice corrente (1-based)<\/td><\/tr>\n          <tr><td><code>loop::is_first<\/code><\/td><td><code>true<\/code> se &egrave; il primo elemento<\/td><\/tr>\n          <tr><td><code>loop::is_last<\/code><\/td><td><code>true<\/code> se &egrave; l'ultimo elemento<\/td><\/tr>\n          <tr><td><code>loop::total<\/code><\/td><td>Numero totale di elementi<\/td><\/tr>\n          <tr><td><code>loop::odd<\/code><\/td><td><code>true<\/code> se l'indice (1-based) &egrave; dispari<\/td><\/tr>\n          <tr><td><code>loop::even<\/code><\/td><td><code>true<\/code> se l'indice (1-based) &egrave; pari<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n\n    <h3 class=\"mt-5\">Modificatori<\/h3>\n    <p>I modificatori trasformano i valori usando la sintassi pipe (<code>|<\/code>). Si possono concatenare: <code>&#123;&#123; var | mod1 | mod2 &#125;&#125;<\/code><\/p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Modificatore<\/th><th>Esempio<\/th><th>Risultato<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td>upper<\/td><td><code>&#123;&#123; nome | upper &#125;&#125;<\/code><\/td><td>MAIUSCOLO<\/td><\/tr>\n          <tr><td>lower<\/td><td><code>&#123;&#123; nome | lower &#125;&#125;<\/code><\/td><td>minuscolo<\/td><\/tr>\n          <tr><td>capitalize<\/td><td><code>&#123;&#123; nome | capitalize &#125;&#125;<\/code><\/td><td>Prima Lettera Maiuscola<\/td><\/tr>\n          <tr><td>raw<\/td><td><code>&#123;&#123; html | raw &#125;&#125;<\/code><\/td><td>Disabilita traduzione ed escaping<\/td><\/tr>\n          <tr><td>nt<\/td><td><code>&#123;&#123; testo | nt &#125;&#125;<\/code><\/td><td>Disabilita solo traduzione (No Translation)<\/td><\/tr>\n          <tr><td>t<\/td><td><code>&#123;&#123; id | t &#125;&#125;<\/code><\/td><td>Forza traduzione<\/td><\/tr>\n          <tr><td>escape<\/td><td><code>&#123;&#123; testo | escape &#125;&#125;<\/code><\/td><td>Forza escaping HTML<\/td><\/tr>\n          <tr><td>date<\/td><td><code>&#123;&#123; data | date:'d\/m\/Y' &#125;&#125;<\/code><\/td><td>Formattazione data<\/td><\/tr>\n          <tr><td>id_safe<\/td><td><code>&#123;&#123; 'Menu Item' | id_safe &#125;&#125;<\/code><\/td><td>Menu_Item (ID-safe)<\/td><\/tr>\n          <tr><td>count<\/td><td><code>&#123;&#123; items | count &#125;&#125;<\/code><\/td><td>Conta elementi array<\/td><\/tr>\n          <tr><td>keys<\/td><td><code>&#123;&#123; obj | keys &#125;&#125;<\/code><\/td><td>Chiavi array (a, b, c)<\/td><\/tr>\n          <tr><td>add<\/td><td><code>&#123;&#123; prezzo | add:10 &#125;&#125;<\/code><\/td><td>Somma un numero<\/td><\/tr>\n          <tr><td>sub<\/td><td><code>&#123;&#123; prezzo | sub:10 &#125;&#125;<\/code><\/td><td>Sottrae un numero<\/td><\/tr>\n          <tr><td>multiply<\/td><td><code>&#123;&#123; prezzo | multiply:1.22 &#125;&#125;<\/code><\/td><td>Moltiplica per un numero<\/td><\/tr>\n          <tr><td>divide<\/td><td><code>&#123;&#123; totale | divide:2 &#125;&#125;<\/code><\/td><td>Divide per un numero<\/td><\/tr>\n          <tr><td>number_format<\/td><td><code>&#123;&#123; prezzo | number_format:'%.2f' &#125;&#125;<\/code><\/td><td>Formattazione numerica<\/td><\/tr>\n          <tr><td>debug<\/td><td><code>&#123;&#123; dati | debug &#125;&#125;<\/code><\/td><td>Output di debug (print_r)<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n    <h4 class=\"mt-3\">Esempio pratico con modificatori concatenati<\/h4>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template<\/div>\n<code>&lt;p&gt;Prezzo IVA inclusa: &#123;&#123; product::price | multiply:1.22 | number_format:'&euro;%.2f' &#125;&#125;&lt;\/p&gt;\n&lt;div id=\"section-&#123;&#123; section::title | id_safe &#125;&#125;\"&gt;...&lt;\/div&gt;<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Valori di default con <code>??<\/code><\/h3>\n    <p>Usa <code>??<\/code> per specificare un valore di default quando la variabile &egrave; vuota o non esiste:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template<\/div>\n<code>&#123;&#123; page::title ?? 'Pagina senza titolo' &#125;&#125;\n&#123;&#123; user::avatar ?? '\/images\/default-avatar.png' &#125;&#125;<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Operatore ternario<\/h3>\n    <p>Scegli tra due valori in base a una condizione:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template<\/div>\n<code>&lt;div class=\"item&#123;&#123; active ? ' active' : '' &#125;&#125;\"&gt;\n&lt;span&gt;&#123;&#123; logged_in ? 'Benvenuto!' : 'Accedi' &#125;&#125;&lt;\/span&gt;\n&lt;span class=\"&#123;&#123; status == 'active' ? 'text-success' : 'text-muted' &#125;&#125;\"&gt;<\/code>\n    <\/div>\n    <p class=\"mt-2\">Funziona anche nei cicli con variabili di loop: <code>&#123;&#123; loop::first ? ' first' : '' &#125;&#125;<\/code><\/p>\n\n    <h3 class=\"mt-5\">Cardinalit&agrave;<\/h3>\n    <p>Mostra contenuto diverso in base al numero di elementi in un array:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;empty from=\"results\"]\n  &lt;p&gt;Nessun risultato trovato.&lt;\/p&gt;\n&#91;\/empty]\n\n&#91;single from=\"results\"]\n  &lt;p&gt;Trovato un risultato:&lt;\/p&gt;\n  &lt;div&gt;&#123;&#123; results::0::title &#125;&#125;&lt;\/div&gt;\n&#91;\/single]\n\n&#91;multiple from=\"results\"]\n  &lt;p&gt;Trovati &#123;&#123; results | count &#125;&#125; risultati:&lt;\/p&gt;\n  &#91;foreach from=\"results\" item=\"result\"]\n    &lt;li&gt;&#123;&#123; result::title &#125;&#125;&lt;\/li&gt;\n  &#91;\/foreach]\n&#91;\/multiple]<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Switch<\/h3>\n    <p>Gestisci pi&ugrave; condizioni in modo pulito:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;switch]\n  &#91;case condition=\"order::status == 'pending'\"]\n    &lt;span class=\"badge yellow\"&gt;In attesa&lt;\/span&gt;\n  &#91;\/case]\n  &#91;case condition=\"order::status == 'shipped'\"]\n    &lt;span class=\"badge green\"&gt;Spedito&lt;\/span&gt;\n  &#91;\/case]\n  &#91;default]\n    &lt;span class=\"badge gray\"&gt;Sconosciuto&lt;\/span&gt;\n  &#91;\/default]\n&#91;\/switch]<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Include<\/h3>\n    <p>Includi altri file template:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;include file=\"header.html\"]\n&#91;include file=\"components\/card.html\" module=\"products\"]<\/code>\n    <\/div>\n    <p class=\"mt-2\">Richiede la configurazione di un <code>include_resolver<\/code> tramite <code>SetIncludeResolver()<\/code>.<\/p>\n\n    <h3 class=\"mt-5\">Permessi<\/h3>\n    <p>Mostra contenuto solo se l'utente ha il permesso specificato:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template Syntax<\/div>\n<code>&#91;permission can_edit]\n  &lt;button class=\"btn-edit\"&gt;Modifica&lt;\/button&gt;\n&#91;\/permission]\n\n&#91;permission can_delete]\n  &lt;button class=\"btn-delete\"&gt;Elimina&lt;\/button&gt;\n&#91;\/permission]<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Attributi condizionali<\/h3>\n    <p>Aggiungi classi CSS o attributi HTML condizionalmente:<\/p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Attributo<\/th><th>Sintassi<\/th><th>Descrizione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>data-dressapi-class-if<\/code><\/td><td><code>condizione:classe<\/code><\/td><td>Aggiunge una classe CSS se la condizione &egrave; vera<\/td><\/tr>\n          <tr><td><code>data-dressapi-attr-if<\/code><\/td><td><code>condizione:attributo:valore<\/code><\/td><td>Aggiunge un attributo HTML se la condizione &egrave; vera<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Template<\/div>\n<code>&lt;div data-dressapi-class-if=\"product::featured:featured\"&gt;&#123;&#123; product::name &#125;&#125;&lt;\/div&gt;\n&lt;a data-dressapi-attr-if=\"item::external:target:_blank\"&gt;Link&lt;\/a&gt;<\/code>\n    <\/div>\n\n    <h3 class=\"mt-5\">Processori Pre\/Post<\/h3>\n    <p>Ogni modulo pu&ograve; definire processori eseguiti prima e dopo il rendering:<\/p>\n    <ul>\n      <li><code>PreProcess.php<\/code> &ndash; Preparazione dati prima del rendering<\/li>\n      <li><code>PostProcess.php<\/code> &ndash; Manipolazione output dopo il rendering<\/li>\n    <\/ul>\n\n    <h3 class=\"mt-5\">Limiti e problemi noti<\/h3>\n    <h4 class=\"mt-3\">&#91;if-exists] dentro &#91;foreach]<\/h4>\n    <p><strong>Problema critico<\/strong>: I tag <code>&#91;if-exists]<\/code> vengono elaborati durante il pre-processing, PRIMA che i cicli <code>&#91;foreach]<\/code> vengano eseguiti. La variabile dell'item non esiste ancora.<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Soluzione consigliata<\/div>\n<code>&lt;!-- Usa fallback con ?? --&gt;\n&#91;foreach from=\"products\" item=\"product\"]\n  &lt;img src=\"&#123;&#123; product::image ?? '\/no-image.png' | raw &#125;&#125;\"&gt;\n&#91;\/foreach]\n\n&lt;!-- Oppure usa &#91;if] che viene valutato durante il DOM processing --&gt;\n&#91;foreach from=\"products\" item=\"product\"]\n  &#91;if(product::image)]\n    &lt;img src=\"&#123;&#123; product::image | raw &#125;&#125;\"&gt;\n  &#91;\/if]\n&#91;\/foreach]<\/code>\n    <\/div>\n    <h4 class=\"mt-3\">Booleani JSON<\/h4>\n    <p>I booleani JSON vengono convertiti in stringhe: <code>true<\/code> &rarr; <code>\"1\"<\/code>, <code>false<\/code> &rarr; <code>\"\"<\/code> (stringa vuota).<\/p>\n    <h4 class=\"mt-3\">Variabili undefined<\/h4>\n    <p>&Egrave; buona pratica usare sempre <code>??<\/code> per variabili che potrebbero non esistere:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">Best Practice<\/div>\n<code>&#123;&#123; user::avatar ?? '\/default.png' &#125;&#125;<\/code>\n    <\/div>\n  <\/div>\n<\/section>\n\n<section class=\"da-section text-center\">\n  <a href=\"\/docs\/CHtmlRender-Manual-IT.pdf\" class=\"btn btn-outline-secondary me-3\" target=\"_blank\"><i class=\"bi bi-file-earmark-pdf\"><\/i> Manuale PDF (IT)<\/a>\n  <a href=\"\/docs\/CHtmlRender-Manual-EN.pdf\" class=\"btn btn-outline-secondary me-3\" target=\"_blank\"><i class=\"bi bi-file-earmark-pdf\"><\/i> PDF Manual (EN)<\/a>\n  <a href=\"\/tutorials\" class=\"btn btn-outline-primary\">&larr; Torna ai Tutorial<\/a>\n<\/section>","description":"Sintassi dei template CHtmlRender","meta_keywords":"","visible":"yes","status":"public","creation_date":"0000-00-00","id__user":1,"priority":0,"groupname":"TUTORIAL"}],"module":"pages","permissions":{"can_read":true},"main_item_title":"title","related_tables":[{"name":"Newsonpage","module":"newsonpage","FK":"id_cmspage","permissions":[]}],"page_info":{"table":"","key":"id","url":"\/pages","url_list":"\/pages","filters":{"id":["=","7007"]},"pagination":{"total_items":23,"page":1,"total_pages":2,"step":1,"items_per_page":20,"url_prev":"\/pages","url_next":"\/pages\/p\/2","url_tmpl":"\/pages\/p\/[[p]]","url_tmpl_with_order":"\/pages\/p\/[[p]]\/ob\/[[ob]]"},"order":{"field":"id","type":"DESC","url_tmpl":"\/pages\/p\/[[p]]"},"module":{"title":"Pages","description":"List of pages","name":"pages"},"current":{"title":"Pages","description":"List of pages","name":"pages","url":"\/tutorials\/template-engine"}},"components":{"alert":{"alert1":[{"type":"warning","message":"OK COMPONENT!"},{"type":"danger","message":"ERROR COMPONENT!"}]}},"messages":[]}