📝 Smarty — Referencia para temas PrestaShop
PrestaShop 1.7 y 8.x usan Smarty 3 como motor de templates en el front office. Los templates .tpl tienen acceso a todas las variables asignadas por el controlador, plugins especiales de PrestaShop y el sistema de herencia {extends}/{block}.
El front office (tienda) usa Smarty. El back office moderno (PS 1.7.6+) usa Twig. Si desarrollas un modulo con paginas de admin modernas, necesitaras Twig. Si desarrollas templates del tema o de hooks de FO, usaras Smarty.
#Herencia de templates (extends/block)
El patron de herencia de Smarty permite definir un layout base y sobreescribir bloques especificos en templates hijos. Casi todos los templates del tema Classic heredan de page.tpl.
{extends file='page.tpl'}
{block name='content_wrapper'}
<div id="content-wrapper">
{block name='content'}{/block}
</div>
{/block}
{extends file='layouts/layout-left-column.tpl'}
{block name='content'}
<section id="main">
<h1 class="h1">{$category.name}</h1>
{if $category.description}
<div class="category-description">
{$category.description nofilter}
</div>
{/if}
{block name='category_products'}
{include file='catalog/listing/products.tpl' listing=$listing}
{/block}
</section>
{/block}
#Includes y fetch
{* Include simple *}
{include file='_partials/breadcrumb.tpl'}
{* Include con variables extra *}
{include file='catalog/listing/product-list.tpl' products=$products}
{* Include desde un modulo especifico (override de tema) *}
{include file='module:ps_imageslider/views/templates/hook/slider.tpl'}
{* Fetch — captura output a una variable *}
{capture name='sidebar_content'}
{include file='_partials/sidebar.tpl'}
{/capture}
{$smarty.capture.sidebar_content}
#Plugin {l} — Traducciones
El plugin {l} es el mecanismo de traduccion de Smarty en PrestaShop. Extrae cadenas para traduccion y las sustituye en tiempo de ejecucion por el idioma activo.
{* Traduccion basica — dominio del tema *}
{l s='Add to cart' d='Shop.Theme.Actions'}
{* Con parametros de sustitucion *}
{l s='Hello %s!' sprintf=[$customer.firstname] d='Shop.Theme.Global'}
{* Traduccion en un modulo *}
{l s='Configure' mod='mymodule'}
{* Dominios comunes de PS *}
{* Shop.Theme.Actions — botones de accion (Agregar, Continuar) *}
{* Shop.Theme.Global — textos generales *}
{* Shop.Theme.Catalog — catalogo de productos *}
{* Shop.Theme.Checkout — proceso de pago *}
{* Shop.Theme.CustomerAccount — area de cliente *}
{* Global.Actions — acciones globales BO/FO *}
#Plugin {url} — URLs
{* URL del carrito *}
{url entity='cart' action='show'}
{* URL de un modulo FO *}
{url entity='module' name='mymodule' controller='main'}
{* URL de una pagina CMS *}
{url entity='cms' id=$cms.id}
{* URL de una categoria *}
{url entity='category' id=$category.id}
{* URL de un producto *}
{url entity='product' id=$product.id}
{* URL estatica (imagen del tema) *}
{$urls.theme_assets}css/theme.css
{$urls.img_ps_url}logo.png
#Plugin {widget} — Widgets de modulos
El plugin {widget} permite insertar el output de un modulo en cualquier lugar del template sin necesidad de un hook especifico. Util para insertar bloques de modulos en posiciones no-standard.
{* Renderizar el output de un modulo directamente *}
{widget name='ps_linklist' hook='displayLeftColumn'}
{* Con parametros adicionales *}
{widget name='ps_categoryproducts' id_category=3}
{* El modulo debe implementar el metodo renderWidget() *}
#Plugin {hook} — Hooks en templates
{* Hook basico *}
{hook h='displayHeader'}
{* Hook con parametros extra *}
{hook h='displayProductButtons' product=$product}
{* Hook de columna lateral *}
{hook h='displayLeftColumn'}
{* Hook de home *}
{hook h='displayHome'}
{* Hooks tipicos en las paginas principales *}
{hook h='displayBanner'} {* Banner superior *}
{hook h='displayTop'} {* Encima del menu *}
{hook h='displayNav1'} {* Navegacion superior izquierda *}
{hook h='displayNav2'} {* Navegacion superior derecha *}
{hook h='displayNotifications'} {* Mensajes flash *}
{hook h='displayFooter'} {* Pie de pagina *}
#Condicionales y bucles
{* Condicional if/elseif/else *}
{if $product.quantity > 0}
<span class="in-stock">{l s='In stock' d='Shop.Theme.Catalog'}</span>
{elseif $product.quantity == 0 && $product.allow_oosp}
<span class="available">{l s='Available on order' d='Shop.Theme.Catalog'}</span>
{else}
<span class="out-of-stock">{l s='Out of stock' d='Shop.Theme.Catalog'}</span>
{/if}
{* Bucle foreach *}
{foreach from=$products item=product name=product_loop}
<article class="product-miniature js-product-miniature">
<h2>{$product.name}</h2>
<span>{$product.price}</span>
</article>
{if $smarty.foreach.product_loop.last}
{* Ultimo elemento *}
{/if}
{foreachelse}
<p>{l s='No products found' d='Shop.Theme.Catalog'}</p>
{/foreach}
{* isset y not empty *}
{if isset($variable) && $variable neq ''}
{$variable}
{/if}
#Modificadores Smarty
{* escape — evitar XSS *}
{$variable|escape:'html'}
{$variable|escape:'url'}
{* truncate — acortar texto *}
{$product.description|truncate:150:'...'}
{* strip_tags — limpiar HTML *}
{$product.description_short|strip_tags|truncate:100}
{* date_format *}
{$order.date_add|date_format:'%d/%m/%Y'}
{* count *}
{$products|count} productos
{* nofilter — HTML sin escapar (solo datos de confianza) *}
{$cms.content nofilter}
{* default — valor por defecto *}
{$variable|default:'Valor por defecto'}
#Debug y desarrollo
{* Ver todas las variables disponibles *}
{debug}
{* Ver el contenido de una variable *}
{$variable|@print_r}
{* Comentarios que no se renderizan *}
{* Este es un comentario Smarty *}
{* Deshabilitar el motor temporalmente *}
{literal}
Este bloque no sera procesado por Smarty: {$variable}
{/literal}
Activa el modo debug de PrestaShop en /config/defines.inc.php estableciendo define('_PS_MODE_DEV_', true);. Esto desactiva la cache de Smarty y muestra errores completos. Nunca en produccion.