Helpers y Filtros de Twig¶
El motor Twig expone el puente phtml de MageObsidian como funciones Twig, y los escapers conscientes del contexto de Magento como filtros. Reflejan los métodos que ya usas en .phtml.
El bloque que renderiza se lee automáticamente del contexto de Twig, asà que los renders anidados y recursivos cada uno apunta a su propio bloque —nunca le pasas block a estos helpers.
Funciones¶
| Función | Mapea a | Devuelve |
|---|---|---|
render_vue(name, props = {}, eager = false, server_html = '', hydrate = false) |
renderVueComponent() |
Un marcador de isla Vue (HTML seguro). |
__(text, ...args) |
El __() de Magento |
Texto traducido con sustitución de argumentos %1/%2 (auto-escapado). |
child_html(alias = '', use_cache = true) |
getChildHtml() |
El HTML de un bloque hijo (seguro). |
hero_icon(name, set = 'solid', size = '24', class = '') |
getHeroIcon() |
Un <svg> de Heroicons (seguro). |
vite_url(path) |
getViteFileUrl() |
URL de un archivo generado por Vite. |
component_path(name) |
resolveComponentPath() |
URL resuelta de un componente por su nombre Vendor::Component. |
view_file_url(file_id, params = {}) |
getViewFileUrl() |
URL de un archivo de vista. |
json_ld(type, data = {}) |
renderJsonLd() |
Un <script> JSON-LD de schema.org para un tipo personalizado (HTML seguro). |
image(src, options = {}) |
renderImage() |
Un <img>/<picture> amigable con CWV (HTML seguro). |
Twig admite argumentos nombrados, que vale la pena usar en cuanto una llamada llega a la cola de la firma de render_vue:
Los helpers que emiten markup (render_vue, child_html, hero_icon, json_ld, image) están marcados como seguros, asà que el auto-escaping de Twig deja su HTML intacto. Los helpers de URL devuelven cadenas planas y se auto-escapan como cualquier valor.
Nota:
render_vue,hero_icon,vite_url,component_path,json_ldeimagerequieren que el bloque que renderiza extiendaMageObsidian\ModernFrontend\Block\Template. Si un.twiglo renderiza un bloque no relacionado, el helper lanza un error accionable que nombra el método ausente.child_htmlyview_file_urlfuncionan en cualquier bloque de Magento;__es independiente del bloque.
Helpers de formato¶
Una segunda extensión (FormatExtension) añade formato a nivel de framework, respaldado por servicios de Magento (no por el bloque, asà que funcionan en cualquier .twig). Toda la salida es texto plano y se auto-escapa —ninguno está marcado como seguro. Cada uno tolera entrada null/vacÃa.
| Helper | Respaldado por | Uso |
|---|---|---|
value\|number |
LocaleFormatter |
Agrupa un número según el locale de la tienda (1234567 → 1,234,567). |
date\|date_format(format = 'medium', part = 'date') |
TimezoneInterface |
Fecha por locale/zona horaria. format: short\|medium\|long\|full; part: date\|time\|datetime. |
html\|strip_tags(allowed = null) |
Filter\StripTags |
Quita el markup dejando texto plano. |
config(path, scope = 'store') |
ScopeConfigInterface |
Un valor de configuración de tienda. |
url(route, params = {}) |
UrlInterface |
Una URL de framework para una ruta. |
media_url(path) |
base media de la tienda | Una URL bajo la base media de la tienda. |
El formato de comercio vive en el PriceExtension del módulo storefront (registrado en el motor vÃa DI — ver Extender el motor): amount\|price(include_container = true) y amount\|currency(code = null), ambos is_safe html porque PriceCurrency::format() devuelve un <span class="price">.
Ejemplos¶
render_vuemonta el componente con la estrategiavisible(perezosa) por defecto. Para una isla por encima del pliegue (header, trigger del mini-cart), pasatruecomo tercer argumento para montarlaeager—reflejando$block->renderVueComponent($name, $props, true)en.phtml.
Filtros¶
El escape de HTML ya es el default de Twig, asà que no hay un filtro escape_html —basta con imprimir un valor. Los demás escapers conscientes del contexto reflejan el $escaper->escape* de Magento para los casos donde el escape de HTML es el contexto equivocado:
| Filtro | Mapea a | Úsalo para |
|---|---|---|
escape_url |
escapeUrl() |
Un valor en un href/src. |
escape_html_attr |
escapeHtmlAttr() |
Un valor en un atributo HTML. |
escape_js |
escapeJs() |
Un valor inyectado en un contexto JS. |
escape_css |
escapeCss() |
Un valor inyectado en un contexto CSS. |
Ejemplos¶
Nombrar una plantilla: namespaces¶
Una referencia a plantilla se puede escribir como Vendor_Module::path.twig, o con un namespace: @catalog/path.twig. Ambas se resuelven por el fallback de temas de Magento, asà que un tema hijo sobrescribe cualquiera de ellas igual que un .phtml.
Los namespaces se derivan de la lista de módulos habilitados en vez de declararse, asà que no hay nada que registrar:
| Módulo | Siempre | Además, mientras ningún otro módulo lo reclame |
|---|---|---|
Magento_Catalog |
@magento-catalog |
@catalog |
MageObsidian_Storefront |
@mage-obsidian-storefront |
@storefront |
La forma con vendor nunca colisiona y nunca cambia, asà que es la que una plantilla puede usar sin condiciones. La corta es la comodidad.
Cuando dos vendors publican el mismo nombre de módulo, el desempate lo gana el que realmente contiene plantillas — MageObsidian_Catalog extiende a Magento_Catalog con código y JS pero no envÃa ningún view/*/templates, asà que @catalog es el del módulo core. Un empate que ninguno o ambos pueden romper se deja sin registrar en vez de decidirlo en silencio; decláralo en di.xml para zanjarlo:
bin/magento mage-obsidian:twig:namespaces imprime la tabla resuelta y marca los nombres cortos perdidos por una colisión. Un namespace desconocido falla al cargar, sugiriendo los más parecidos.
Composición: includes, embeds y macros¶
Todas las referencias usan la notación Vendor_Module::path.twig, resuelta por el fallback de temas de Magento —asà que un tema hijo sobrescribe cualquier partial/macro igual que un .phtml. Prefiere componer plantillas antes que copiar markup.
{% extends %} + {% block %} — una base con regiones sobrescribibles:
@parent — extender la plantilla que estás sobrescribiendo. Un override de tema no puede hacer {% extends %} de su propio nombre: el fallback lo resuelve de vuelta al override y Twig entra en recursión. @parent es la copia un nivel más arriba de la cadena — la del tema padre, o la del módulo si no hay ninguno:
Cada copia resuelve su propio nivel, asà que una cadena de tres temas funciona: el hijo extiende el del padre, el padre el de la base, y la base el del módulo. En una plantilla de módulo es un error — no hay nada por encima.
{% include %} con with/only — un partial parametrizado (only aÃsla el scope del partial):
only también descarta block
render_vue, hero_icon, image y json_ld leen el bloque que renderiza desde el contexto. Una parcial incluida con only no lo hereda, asà que pásalo — with { block: block, … } only — o el helper lanza un error diciendo exactamente esto.
{% embed %} — el equivalente de slots en Twig. Incluye una carcasa y rellena sus bloques en el sitio de llamada. Ideal para cards/secciones cuyo armazón es compartido pero el contenido varÃa:
{% macro %} — fragmentos reutilizables sin pasar por layout. Importa una vez, llama muchas:
ViewModels en Twig¶
Mantén la lógica de datos fuera de la plantilla: ponla en un ViewModel (ArgumentInterface), regÃstralo como <argument> del bloque en el layout, y léelo desde Twig con el getter mágico del bloque.
El mismo ViewModel puede registrarse en varios bloques (header, footer, …) para compartir una sola fuente de verdad —sin datos duplicados en las plantillas.
Extender el motor Twig¶
El entorno Twig compartido lo construye EnvironmentFactory, cuyo argumento array extensions se mergea entre módulos por clave de item —como el engines de TemplateEngineFactory. Cualquier módulo añade sus filtros/funciones registrando un Twig\Extension\ExtensionInterface en ese array, sin tocar el motor:
Asà es exactamente como el PriceExtension del storefront añade price/currency.
Decláralo en scope global, no en
etc/frontend/di.xml. Los argumentos array se mergean acumulativamente dentro de un scope, pero un scope de área reemplaza un array global en vez de mergear —lo que descartarÃa las extensiones del propio motor en el frontend. La extensión solo se instancia al construir el entorno (frontend), asà que una declaración global es inerte en otros lados. Los nombres de filtro/función son un namespace compartido; prefija los de terceros para evitar colisiones (gana el último).
Próximos Pasos¶
- Motor Twig — instalación y cómo Twig coexiste con phtml.
- Islas Vue — qué emite
render_vuey cómo se hidrata.