Volt: Motor de plantillas

Resumen
Volt es un motor de plantillas ultrarrápido y de diseño amigable, escrito en C para PHP. Ofrece un conjunto de ayudantes para escribir las vistas fácilmente. Volt is highly integrated with other components of Phalcon, but can be used as a stand-alone component in your application.

Volt is inspired by Jinja, originally created by Armin Ronacher.
Muchos desarrolladores estarán en territorio familiar al utilizar la misma sintaxis que han estado utilizando con motores de plantillas similares. La sintaxis y características de Volt se han mejorado con más elementos y, por supuesto, con el rendimiento al que los desarrolladores han estado acostumbrados mientras trabajan con Phalcon.
Sintaxis
Las vistas de Volt se compilan a código PHP puro, así que, básicamente ahorran el esfuerzo de escribir el código PHP manualmente:
{% for invoice in invoices %}
<div class='row'>
<div>
ID: {{ invoice.inv_id }}
</div>
<div>
{%- if 1 === invoice.inv_status_flag -%}
Paid
{%- else -%}
Unpaid
{%- endif -%}
</div>
<div>
{{ invoice.inv_description }}
</div>
<div>
{{ invoice.inv_total }}
</div>
</div>
{% endfor %}
comparado con:
<?php foreach ($invoices as $invoice) { ?>
<div class='row'>
<div>
ID: <?= $invoice->inv_id; ?>
</div>
<div>
<?php if (1 === $invoice->inv_status_flag) { ?>
Paid
<?php } else { ?>
Unpaid
<?php } ?>
</div>
<div>
<?= $invoice->inv_description; ?>
</div>
<div>
<?= $invoice->total; ?>
</div>
</div>
<?php } ?>
Constructor
public function __construct(
ViewBaseInterface $view,
DiInterface $container = null
)
El constructor acepta un Phalcon\Mvc\View o cualquier componente que implemente la ViewBaseInterface
, y un contenedor DI.
Métodos
Hay varios métodos disponibles en Volt. En la mayoría de los casos, sólo un puñado de ellos se utilizan en aplicaciones modernas.
callMacro(string $name, array $arguments = []): mixed
Comprueba si una macro está definida y la llama
convertEncoding(string $text, string $from, string $to): string
Realiza una conversión cadena
Devuelve el compilador del Volt
Devuelve la salida almacenada en caché en otra etapa de visualización
Obtener las opciones de Volt
getView(): ViewBaseInterface
Devuelve el componente de vista relacionados con el adaptador
isIncluded(mixed $needle, mixed $haystack): bool
Comprueba si se incluye la aguja en el pajar
Filtro de longitud. Si se pasa un objeto o matriz se realiza un count()
, de lo contrario realiza un strlen()<code>/
mb_strlen()</code>
partial(string $partialPath, mixed $params = null): string
Representa una vista parcial dentro de otro punto de vista
render(string $templatePath, mixed $params, bool $mustClean = false)
Renderiza una vista utilizando el motor de plantillas
setOptions(array $options)
Establecer las opciones del Volt
slice(mixed $value, int $start = 0, mixed $end = null)
Extrae un trozo de un valor de un string/array/objecto iterable
sort(array $value): array
Ordena una matriz
Activación
Como con otros motores de plantillas, se puede registrar Volt en el componente de la vista, usando una nueva extensión o reusar el estándar phtml
:
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\ViewBaseInterface;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;
$container = new FactoryDefault();
$container->setShared(
'voltService',
function (ViewBaseInterface $view) use ($container) {
$volt = new Volt($view, $container);
$volt->setOptions(
[
'always' => true,
'extension' => '.php',
'separator' => '_',
'stat' => true,
'path' => appPath('storage/cache/volt/'),
'prefix' => '-prefix-',
]
);
return $volt;
}
);
$container->set(
'view',
function () {
$view = new View();
$view->setViewsDir('../app/views/');
$view->registerEngines(
[
'.volt' => 'voltService',
]
);
return $view;
}
);
Para utilizar la extensión estándar phtml
:
<?php
$view->registerEngines(
[
'.phtml' => 'voltService',
]
);
No tienes que especificar el servicio Volt en el DI; también puede utilizar el motor de Volt con la configuración predeterminada:
<?php
use Phalcon\Mvc\View\Engine\Volt;
$view->registerEngines(
[
'.volt' => Volt::class,
]
);
Si no quieres reutilizar Volt como un servicio, puedes pasar una función anónima para registrar el motor en lugar de un nombre de servicio:
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\ViewBaseInterface;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;
$container = new FactoryDefault();
$container->set(
'view',
function () {
$view = new View();
$view->setViewsDir('../app/views/');
$view->registerEngines(
[
'.volt' => function (ViewBaseInterface $view) {
$volt = new Volt($view, $this);
$volt->setOptions(
[
'always' => true,
'extension' => '.php',
'separator' => '_',
'stat' => true,
'path' => appPath('storage/cache/volt/'),
'prefix' => '-prefix-',
]
);
return $volt;
}
]
);
return $view;
}
);
Las siguientes opciones están disponibles en Volt:
Opción |
Predeterminado |
Descripción |
autoescape |
false |
Habilita el autoescape HTML globalmente |
always |
false |
Si se deben compilar las plantillas en cada petición o cuando cambian |
extension |
.php |
Extensión adicional añadida al fichero PHP compilado |
path |
./ |
Una ruta escribible donde se colocarán las plantillas PHP compiladas |
separator |
%% |
Sustituye los separadores de directorio / and \ con este separador para poder crear un único fichero en el directorio compilado |
prefix |
null |
Antepone un prefijo a las plantillas en la ruta de compilación |
stat |
true |
Si Phalcon debe comprobar si hay diferencias entre el fichero de plantilla y su ruta compilada |
La ruta de compilación se genera de acuerdo a las opciones anteriores. Sin embargo, tiene total libertad para definir la ruta de compilación como una función anónima, incluyendo la lógica usada para generarla. The anonymous function receives the relative path to the template in the predefined views
directory.
Añadir extensiones
Añadir la extensión .php
a la ruta de plantilla, dejando las plantillas compiladas en el mismo directorio:
<?php
$volt->setOptions(
[
'path' => function ($templatePath) {
return $templatePath . '.php';
}
]
);
Directorios diferentes
El siguiente ejemplo creará la misma estructura en directorios diferentes
<?php
$volt->setOptions(
[
'path' => function (string $templatePath) {
$dirName = dirname($templatePath);
if (true !== is_dir('cache/' . $dirName)) {
mkdir(
'cache/' . $dirName,
0777,
true
);
}
return 'cache/' . $dirName . '/' . $templatePath . '.php';
}
]
);
Uso
Volt usa delimitadores específicos para su sintaxis. {% ... %}
is used to execute statements such as for-loops or assign values and {{ ... }}
prints the result of an expression to the template. Los ficheros de vistas también pueden contener PHP y HTML si así lo desea.
Abajo se muestra un ejemplo de plantilla que ilustra unos pocos conceptos básicos:
{# app/views/posts/show.phtml #}
<!DOCTYPE html>
<html>
<head>
<title>{{ title }} - An example blog</title>
</head>
<body>
{% if true === showNavigation %}
<ul id='navigation'>
{% for item in menu %}
<li>
<a href='{{ item.href }}'>
{{ item.caption }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
<h1>{{ post.title }}</h1>
<div class='content'>
{{ post.content }}
</div>
</body>
</html>
Using Phalcon\Mvc\View you can pass variables from the controller to the views. En el ejemplo anterior, se pasaron cuatro variables a la vista: showNavigation
, menu
, title
y post
:
<?php
use MyApp\Models\Menu;
use MyApp\Models\Post;
use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;
/**
* @property View $view
*/
class PostsController extends Controller
{
public function showAction()
{
$post = Post::findFirst();
$menu = Menu::findFirst();
$this->view->showNavigation = true;
$this->view->menu = $menu;
$this->view->title = $post->title;
$this->view->post = $post;
// Or...
$this->view->setVar('showNavigation', true);
$this->view->setVar('menu', $menu);
$this->view->setVar('title', $post->title);
$this->view->setVar('post', $post);
}
}
NOTE The placeholders for Volt {{
, }}
, {%
and %}
cannot be changed or set.
Vue.js
If you are using Vue you will need to change the interpolators in Vue itself:
new Vue(
{
el: '#app',
data: data,
delimiters: ["<%","%>"]
}
);
Angular
If you are using Angular you can set the interpolators as follows:
var myApp = angular.module('myApp', []);
myApp.config(
function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
}
);
Variables
Las variables de objetos pueden tener atributos, que se pueden acceder utilizando la sintaxis: foo.bar
. Si usted está pasando un array, tiene que usar la sintaxis de corchete: foo ['bar']
{{ post.title }} {# for $post->title #}
{{ post['title'] }} {# for $post['title'] #}
Filtros
Las variables pueden ser formateadas o modificación mediante filtros. El operador de tubería o pleca |
se utiliza para aplicar filtros a las variables:
{{ post.title | e }}
{{ post.content | striptags }}
{{ name | capitalize | trim }}
Los filtros incorporados disponibles son:
Filtro |
Descripción |
abs |
Applies the abs PHP function to a value. |
capitalize |
Capitalizes a string by applying the ucwords PHP function to the value |
convert_encoding |
Convierte una cadena de un conjunto de caracteres a otro |
default |
Establece un valor por defecto en caso de que la expresión evaluada esté vacía, no establecida o evalúa a un valor falso |
e |
Applies Phalcon\Html\Escaper->html() to the value |
escape |
Applies Phalcon\Html\Escaper->html() to the value |
escape_attr |
Applies Phalcon\Html\Escaper->attributes() to the value |
escape_css |
Applies Phalcon\Html\Escaper->css() to the value |
escape_js |
Applies Phalcon\Html\Escaper->js() to the value |
format |
Formats a string using sprintf |
json_encode |
Converts a value into its JSON representation |
json_decode |
Converts a value from its JSON representation to a PHP representation |
join |
Joins the array parts using a separator join |
keys |
Returns the array keys using array_keys |
left_trim |
Applies the ltrim PHP function to the value. Elimina los espacios extra |
length |
Counts the string length or how many items are in an array or object, equivalent of count |
lower |
Cambiar una cadena a minúsculas |
nl2br |
Cambia nuevas líneas \n por roturas de línea (<br /> ). Uses the PHP function nl2br |
right_trim |
Applies the rtrim PHP function to the value. Elimina los espacios extra |
slashes |
Applies the addslashes PHP function to the value. |
slice |
Corta cadenas, vectores u objetos atravesables |
sort |
Sorts an array using the PHP function asort |
stripslashes |
Applies the stripslashes PHP function to the value. Elimina comillas escapadas |
striptags |
Applies the striptags PHP function to the value. Elimina etiquetas HTML |
trim |
Applies the trim PHP function to the value. Elimina los espacios extra |
upper |
Applies the strtoupper PHP function to the value. |
url_encode |
Applies the urlencode PHP function to the value |
Ejemplos
{# e or escape filter #}
{{ '<h1>Hello<h1>'|e }}
{{ '<h1>Hello<h1>'|escape }}
{# trim filter #}
{{ ' hello '|trim }}
{# striptags filter #}
{{ '<h1>Hello<h1>'|striptags }}
{# slashes filter #}
{{ ''this is a string''|slashes }}
{# stripslashes filter #}
{{ '\'this is a string\''|stripslashes }}
{# capitalize filter #}
{{ 'hello'|capitalize }}
{# lower filter #}
{{ 'HELLO'|lower }}
{# upper filter #}
{{ 'hello'|upper }}
{# length filter #}
{{ 'invoices'|length }}
{{ [1, 2, 3]|length }}
{# nl2br filter #}
{{ 'some\ntext'|nl2br }}
{# sort filter #}
{% set sorted = [3, 1, 2]|sort %}
{# keys filter #}
{% set keys = ['first': 1, 'second': 2, 'third': 3]|keys %}
{# join filter #}
{% set joined = 'a'..'z'|join(',') %}
{# format filter #}
{{ 'My real name is %s'|format(name) }}
{# json_encode filter #}
{% set encoded = invoices|json_encode %}
{# json_decode filter #}
{% set decoded = '{'one':1,'two':2,'three':3}'|json_decode %}
{# url_encode filter #}
{{ post.permanent_link|url_encode }}
{# convert_encoding filter #}
{{ 'désolé'|convert_encoding('utf8', 'latin1') }}
Comentarios
Comments may also be added to a template using the {# ... #}
delimiters. Todo el texto entre ellos simplemente se ignorará en la salida final:
{# note: this is a comment
{% set price = 100; %}
#}
Estructuras de Control
Volt proporciona un conjunto de estructuras de control básicas pero poderosas para usar en las plantillas:
For
Itera sobre cada elemento de una secuencia. El ejemplo siguiente muestra cómo recorrer un conjunto de invoices
y mostrar cada título:
<h1>Invoices</h1>
<ul>
{% for invoice in invoices %}
<li>
{{ invoice.inv_title | e }}
</li>
{% endfor %}
</ul>
los bucles-for también se pueden anidar:
<h1>Invoices</h1>
{% for invoice in invoices %}
{% for product in invoice.products %}
Product: {{ product.prd_title|e }} {{ product.prd_price|e }} USD <br />
{% endfor %}
{% endfor %}
Puede obtener el elemento keys
como en la homóloga en PHP usando la siguiente sintaxis:
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for name, value in numbers %}
Name: {{ name }} Value: {{ value }} <br />
{% endfor %}
Se puede establecer opcionalmente una evaluación if
:
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for value in numbers if value < 2 %}
Value: {{ value }} <br />
{% endfor %}
{% for name, value in numbers if name !== 'two' %}
Name: {{ name }} Value: {{ value }} <br />
{% endfor %}
Si se define un else
dentro del for
, se ejecutará si la expresión en el iterador resulta en cero iteraciones:
<h1>Invoices</h1>
{% for invoice in invoices %}
Invoice: {{ invoice.inv_number | e }} - {{ invoice.inv_title | e }} <br />
{% else %}
There are no invoices to show
{% endfor %}
Sintaxis alternativa:
<h1>Invoices</h1>
{% for invoice in invoices %}
Invoice: {{ invoice.inv_number | e }} - {{ invoice.inv_title | e }} <br />
{% elsefor %}
There are no invoices to show
{% endfor %}
Bucles
Las declaraciones de break
y continue
pueden utilizarse para salir de un bucle o forzar una iteración en el bloque actual:
{# skip the even invoices #}
{% for index, invoice in invoices %}
{% if index is even %}
{% continue %}
{% endif %}
...
{% endfor %}
{# exit the foreach on the first even invoice #}
{% for index, invoice in invoices %}
{% if index is even %}
{% break %}
{% endif %}
...
{% endfor %}
If
Como en PHP, una declaración if
comprueba si una expresión se evalúa como verdadera o falsa:
<h1>Paid Invoices</h1>
<ul>
{% for invoice in invoices %}
{% if invoice.inv_paid_flag === 1 %}
<li>{{ invoice.inv_title | e }}</li>
{% endif %}
{% endfor %}
</ul>```
También se admite la cláusula `else`:
```twig
<h1>Invoices</h1>
<ul>
{% for invoice in invoices %}
{% if invoice.inv_paid_flag === 1 %}
<li>{{ invoice.inv_title | e }}</li>
{% else %}
<li>{{ invoice.inv_title | e }} [NOT PAID]</li>
{% endif %}
{% endfor %}
</ul>```
La estructura de flujo de control `elseif` se puede usar junto con `if` para emular un bloque `switch`:
```twig
{% if invoice.inv_paid_flag === constant('MyApp\Constants\Status::PAID') %}
Invoice is paid
{% elseif invoice.inv_paid_flag === 2 %}
Invoice is not paid
{% else %}
Invoice is paid status is not defined
{% endif %}
Switch
Una alternativa a la sentencia if
es switch
, que le permite crear rutas de ejecución lógicas en su aplicación:
{% switch foo %}
{% case 0 %}
{% case 1 %}
{% case 2 %}
"foo" is less than 3 but not negative
{% break %}
{% case 3 %}
"foo" is 3
{% break %}
{% default %}
"foo" is {{ foo }}
{% endswitch %}
La sentencia switch
ejecuta sentencia a sentencia, por lo que la sentencia break
es necesaria en algunos casos. Cualquier salida (incluyendo espacios) entre una sentencia en blanco y el primer case
resultará en error de sintaxis. Empty lines and whitespaces can therefore be cleared to reduce the number of errors see here.
case
sin switch
Lanzará Fatal error: Uncaught Phalcon\Mvc\View\Exception: Unexpected CASE
.
switch
sin endswitch
Lanzará Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected EOF in ..., there is a 'switch' block without 'endswitch'
.
default
sin switch
No lanzará un error porque default
es una palabra reservada para filtros como {{ EXPRESSION | default(VALUE) }}
pero en este caso la expresión solo mostrará un caracter vacío ''
.
switch
anidado
{% switch EXPRESSION %}
{% switch EXPRESSION %}
{% endswitch %}
{% endswitch %}
Lanzará Fatal error: Uncaught Phalcon\Mvc\View\Exception: A nested switch detected. There is no nested switch-case statements support in ... on line ...
un switch
sin una expresión
{% switch %}
{% case EXPRESSION %}
{% break %}
{% endswitch %}
Will throw Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected token%}in ... on line ...
Contexto de Bucle
Una variable especial está disponible dentro de bucles for
para proporcionarle información sobre
Variable |
Descripción |
loop.first |
Verdadero si es la primera iteración. |
loop.index |
La iteración actual del bucle. (indexado 1) |
loop.index0 |
La iteración actual del bucle. (indexado 0) |
loop.length |
El número de elementos a iterar |
loop.last |
Verdadero si está en la última iteración. |
loop.revindex |
El número de iteraciones desde el final del bucle (indexado 1) |
loop.revindex0 |
El número de iteraciones desde el final del bucle (indexado 0) |
Ejemplo:
{% for invoice in invoices %}
{% if loop.first %}
<table>
<tr>
<th>#</th>
<th>Id</th>
<th>Title</th>
</tr>
{% endif %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ invoice.inv_id }}</td>
<td>{{ invoice.inv_title }}</td>
</tr>
{% if loop.last %}
</table>
{% endif %}
{% endfor %}
Asignaciones
Las variables pueden cambiar en una plantilla usando la instrucción set
:
{% set fruits = ['Apple', 'Banana', 'Orange'] %}
{% set title = invoice.inv_title %}
Se permiten las asignaciones múltiples en la misma instrucción:
{% set fruits = ['Apple', 'Banana', 'Orange'], name = invoice.inv_title, active = true %}
Además, puede usar operaciones de asignación compuestos:
{% set price += 100.00 %}
{% set age *= 5 %}
Los siguientes operadores están disponibles:
Operador |
Descripción |
= |
Asignación estándar |
+= |
Asignación de adición |
-= |
Asignación de resta |
\*= |
Asignación de multiplicación |
/= |
Asignación de división |
Expresiones
Volt proporciona un conjunto básico de expresiones, incluyendo literales y operadores comunes. An expression can be evaluated and printed using the {{
and }}
delimiters:
Si una expresión necesita ser evaluada sin imprimirse se puede usar la sentencia do
:
Literales
Se soportan los siguientes literales:
Filtro |
Descripción |
'esto es una cadena' |
Los textos entre doble comillas simples o dobles se tratan como cadenas de caracteres |
100.25 |
Los números con parte decimal se tratan como dobles/flotadores |
100 |
Los número sin parte decimal se tratan como enteros |
false |
La constante false es el valor booleano false |
true |
La constante true es el valor booleano true |
null |
La constante null es el valor null |
Vectores
Puede crear vectores encerrando una lista de valores entre corchetes cuadrados:
{# Simple array #}
{{ ['Apple', 'Banana', 'Orange'] }}
{# Other simple array #}
{{ ['Apple', 1, 2.5, false, null] }}
{# Multi-Dimensional array #}
{{ [[1, 2], [3, 4], [5, 6]] }}
{# Hash-style array #}
{{ ['first': 1, 'second': 4/2, 'third': '3'] }}
Las llaves también se usan para definir vectores o hashes
:
{% set myArray = {'Apple', 'Banana', 'Orange'} %}
{% set myHash = {'first': 1, 'second': 4/2, 'third': '3'} %}
Matemáticas
Puede hacer cálculos en las plantillas usando los siguientes operadores:
Operador |
Descripción |
+ |
Realiza una operación de suma. {{ 2 + 3 }} devuelve 5 |
- |
Realiza una operación de resta {{ 2 - 3 }} devuelve -1 |
* |
Realiza una operación de multiplicación {{ 2 * 3 }} devuelve 6 |
/ |
Realiza una operación de división {{ 10 / 2 }} devuelve 5 |
% |
Calcula el resto de una división entera {{ 10 % 3 }} devuelve 1 |
Comparaciones
Están disponibles los siguientes operadores de comparación:
Operador |
Descripción |
== |
Comprueba si ambos operandos son iguales |
!= |
Comprueba si ambos operandos no son iguales |
<> |
Comprueba si ambos operandos no son iguales |
> |
Comprueba si el operando izquierdo es mayor que el operando derecho |
< |
Comprueba si el operando izquierdo es menor que el operando derecho |
<= |
Comprueba si el operando de la izquierda es menor o igual que el operando derecho |
>= |
Comprueba si el operando izquierdo es mayor o igual que el operando derecho |
=== |
Comprueba si ambos operandos son idénticos |
!== |
Comprueba si ambos operandos no son idénticos |
Lógica
Los operadores lógicos son útiles en la evaluación de la expresión if
para combinar múltiples pruebas:
Operador |
Descripción |
o |
Devuelve true si el operando de la derecha o la izquierda se evalúa como true |
and |
Devuelve true si los operandos izquierdo y derecho se evalúan como verdadero |
not |
Niega una expresión |
( expr ) |
Las expresiones se agrupan entre paréntesis |
Otros operadores
También están disponibles otros operadores:
Operador |
Descripción |
~ |
Concatena ambos operandos {{ 'hello ' ~ 'world' }} |
| |
Applies a filter in the right operand to the left {{ 'hello' | uppercase }} |
.. |
Crea un rango {{ 'a'..'z' }} {{ 1..10 }} |
is |
Alias de == (igual), también realiza pruebas |
in |
Para comprobar si una expresión está contenida en otras expresiones if 'a' in 'abc' |
is not |
Alias de != (no iguales) |
'a' ? 'b' : 'c' |
Operador ternario. El mismo que el operador ternario de PHP |
++ |
Incrementa un valor |
-- |
Decrementa un valor |
El ejemplo siguiente muestra cómo usar los operadores:
{% set fruits = ['Apple', 'Banana', 'Orange', 'Kiwi'] %}
{% for index in 0..fruits | length %}
{% if invoices[index] is defined %}
{{ 'Name: ' ~ invoices[index] }}
{% endif %}
{% endfor %}
Pruebas
Las pruebas de pueden usar para comprobar si una variable tiene un valor esperado válido. Se usa el operador is
para realizar las pruebas:
{% set invoices = ['1': 'Apple', '2': 'Banana', '3': 'Orange'] %}
{% for position, name in invoices %}
{% if position is odd %}
{{ name }}
{% endif %}
{% endfor %}
Están disponibles las siguientes pruebas integradas en Volt:
Prueba |
Descripción |
defined |
Comprueba si una variable esta definida (isset() ) |
divisibleby |
Comprueba si un valor es divisible por otro valor |
empty |
Comprueba si una variable está vacía |
even |
Comprueba si un valor numérico es par |
iterable |
Comprueba si un valor es iterable. Se puede recorrer con una sentencia ‘for’ |
numeric |
Comprueba si el valor es numérico |
odd |
Comprueba si un valor numérico es impar |
sameas |
Comprueba si un valor es idéntico a otro valor |
scalar |
Comprueba si el valor es escalar (no una matriz, objeto o recurso) |
type |
Comprueba si un valor es del tipo especificado |
Más ejemplos:
{% if invoice is defined %}
The invoice variable is defined
{% endif %}
{% if invoice is empty %}
The invoice is null or is not defined
{% endif %}
{% for key, name in [1: 'Apple', 2: 'Banana', 3: 'Orange'] %}
{% if key is even %}
{{ name }}
{% endif %}
{% endfor %}
{% for key, name in [1: 'Apple', 2: 'Banana', 3: 'Orange'] %}
{% if key is odd %}
{{ name }}
{% endif %}
{% endfor %}
{% for key, name in [1: 'Apple', 2: 'Banana', 'third': 'Orange'] %}
{% if key is numeric %}
{{ name }}
{% endif %}
{% endfor %}
{% set invoices = [1: 'Apple', 2: 'Banana'] %}
{% if invoices is iterable %}
{% for invoice in invoices %}
...
{% endfor %}
{% endif %}
{% set world = 'hello' %}
{% if world is sameas('hello') %}
{{ 'it's hello' }}
{% endif %}
{% set external = false %}
{% if external is type('boolean') %}
{{ 'external is false or true' }}
{% endif %}
Macros
Las macros pueden utilizarse para reutilizar la lógica de una plantilla, actúan como funciones PHP, pueden recibir parámetros y devolver valores:
{# Macro 'display a list of links to related topics' #}
{%- macro related_bar(related_links) %}
<ul>
{%- for link in related_links %}
<li>
<a href='{{ url(link.url) }}'
title='{{ link.title|striptags }}'>
{{ link.text }}
</a>
</li>
{%- endfor %}
</ul>
{%- endmacro %}
{# Print related links #}
{{ related_bar(links) }}
<div>This is the content</div>
{# Print related links again #}
{{ related_bar(links) }}
Al llamar a las macros, se pueden pasar parámetros por nombre:
{%- macro error_messages(message, field, type) %}
<div>
<span class='error-type'>{{ type }}</span>
<span class='error-field'>{{ field }}</span>
<span class='error-message'>{{ message }}</span>
</div>
{%- endmacro %}
{# Call the macro #}
{{
error_messages(
'type': 'Invalid',
'message': 'The name is not valid',
'field': 'name'
)
}}
Macros can return values:
{%- macro my_input(name, class) %}
{% return text_field(name, 'class': class) %}
{%- endmacro %}
{# Call the macro #}
{{ '<p>' ~ my_input('name', 'input-text') ~ '</p>' }}
Y recibir parámetros opcionales:
{%- macro my_input(name, class='input-text') %}
{% return text_field(name, 'class': class) %}
{%- endmacro %}
{# Call the macro #}
{{ '<p>' ~ my_input('name') ~ '</p>' }}
{{ '<p>' ~ my_input('name', 'input-text') ~ '</p>' }}
Ayudantes de Etiquetas
Volt is highly integrated with Phalcon\Html\TagFactory, so it’s easy to use the helpers provided by that component in a Volt template:
{{ script().add('js/jquery.js') }}
{{ form(['action' : 'products/save', 'method': 'post']) }}
<label for='name'>Name</label>
{{ inputText('name', null, ['size': 32]) }}
<label for='type'>Type</label>
{% for productType in productTypes }}
{{ inputSelect().addPlaceholder('...').add(productType.name, productType.id) }}
{% for productType in productTypes }}
{{ inputSelect().addPlaceholder('...').add(productType.name, productType.id) }}
{% endfor %}
{{ inputSubmit('Send') }}
{{ close('form') }}
Se genera el siguiente PHP:
<?= $this->tag->script("\t", "\n\n") ?>
<?= $this->tag->form(['products/save', 'method' : 'post']); ?>
<label for='name'>Name</label>
<?= $this->tag->inputText(['name', 'size' : 32]); ?>
<label for='type'>Type</label>
<?php foreach ($productTypes as $productType) { ?>
<?= $this->tag->addPlaceholder('...').add(productType.name, productType.id); ?>
<?php } ?>
<?= $this->tag->inputSubmit('Send'); ?>
<?= $this->tag->close('form'); ?>
You can call any of the helpers that Phalcon\Html\TagFactory provides directly in Volt.
Volt Function |
Clase |
a |
Phalcon\Html\Helper\Anchor |
base |
Phalcon\Html\Helper\Base |
body |
Phalcon\Html\Helper\Body |
button |
Phalcon\Html\Helper\Button |
close |
Phalcon\Html\Helper\Close |
doctype |
Phalcon\Html\Helper\Doctype |
element |
Phalcon\Html\Helper\Element |
form |
Phalcon\Html\Helper\Form |
img |
Phalcon\Html\Helper\Img |
inputCheckbox |
Phalcon\Html\Helper\Input\Checkbox |
inputColor |
Phalcon\Html\Helper\Input\Color |
inputDate |
Phalcon\Html\Helper\Input\Date |
inputDateTime |
Phalcon\Html\Helper\Input\DateTime |
inputDateTimeLocal |
Phalcon\Html\Helper\Input\DateTimeLocal |
inputEmail |
Phalcon\Html\Helper\Input\Email |
inputFile |
Phalcon\Html\Helper\Input\File |
inputHidden |
Phalcon\Html\Helper\Input\Hidden |
inputImage |
Phalcon\Html\Helper\Input\Image |
inputInput |
Phalcon\Html\Helper\Input\Input |
inputMonth |
Phalcon\Html\Helper\Input\Month |
inputNumeric |
Phalcon\Html\Helper\Input\Numeric |
inputPassword |
Phalcon\Html\Helper\Input\Password |
inputRadio |
Phalcon\Html\Helper\Input\Radio |
inputRange |
Phalcon\Html\Helper\Input\Range |
inputSearch |
Phalcon\Html\Helper\Input\Search |
inputSelect |
Phalcon\Html\Helper\Input\Select |
inputSubmit |
Phalcon\Html\Helper\Input\Submit |
inputTel |
Phalcon\Html\Helper\Input\Tel |
inputText |
Phalcon\Html\Helper\Input\Text |
inputTextarea |
Phalcon\Html\Helper\Input\Textarea |
inputTime |
Phalcon\Html\Helper\Input\Time |
inputUrl |
Phalcon\Html\Helper\Input\Url |
inputWeek |
Phalcon\Html\Helper\Input\Week |
label |
Phalcon\Html\Helper\Label |
link |
Phalcon\Html\Helper\Link |
meta |
Phalcon\Html\Helper\Meta |
ol |
Phalcon\Html\Helper\Ol |
script |
Phalcon\Html\Helper\Script |
style |
Phalcon\Html\Helper\Style |
title |
Phalcon\Html\Helper\Title |
ul |
Phalcon\Html\Helper\Ul |
Also, you can use the Phalcon\Tag helper methods. You only need to call an uncamelized version of the method:
Función en Volt |
Método |
check_field |
Phalcon\Tag::checkField |
date_field |
Phalcon\Tag::dateField |
email_field |
Phalcon\Tag::emailField |
end_form |
Phalcon\Tag::endForm |
file_field |
Phalcon\Tag::fileField |
form_legacy |
Phalcon\Tag::form |
friendly_title |
Phalcon\Tag::friendlyTitle |
get_title |
Phalcon\Tag::getTitle |
hidden_field |
Phalcon\Tag::hiddenField |
image |
Phalcon\Tag::image |
javascript_include |
Phalcon\Tag::javascriptInclude |
link_to |
Phalcon\Tag::linkTo |
numeric_field |
Phalcon\Tag::numericField |
password_field |
Phalcon\Tag::passwordField |
radio_field |
Phalcon\Tag::radioField |
select |
Phalcon\Tag::select |
select_static |
Phalcon\Tag::selectStatic |
stylesheet_link |
Phalcon\Tag::stylesheetLink |
submit_button |
Phalcon\Tag::submitButton |
text_area |
Phalcon\Tag::textArea |
text_field |
Phalcon\Tag::textField |
Funciones
Las siguientes funciones integradas están disponibles en Volt:
Nombre |
Descripción |
constant |
Lee una constante PHP |
content |
Incluye el contenido producido en la etapa de renderizado anterior |
date |
Llama a la función PHP con el mismo nombre |
dump |
Llama a la función PHP var_dump() |
get_content |
Lo mismo que content |
partial |
Dinámicamente carga una vista parcial en la plantilla actual |
static_url |
Genera una url estática usando el servicio url |
super |
Renderiza el contenido del bloque padre |
time |
Llama a la función PHP con el mismo nombre |
url |
Genera una URL usando el servicio url |
version |
Devuelve la versión actual del framework |
version_id |
Devuelve el ID de la versión actual del framework |
Vistas
Also, Volt is integrated with Phalcon\Mvc\View, you can play with the view hierarchy and include partials as well:
{{ content() }}
<div id='footer'>
{{ partial('partials/footer') }}
{{ partial('partials/footer', ['links': links]) }}
</div>
Una vista parcial es incluida en tiempo de ejecución, Volt también proporciona include
, esto compila el contenido de una vista y devuelve su contenido como parte de la vista en el que se incluye:
<div id='footer'>
{% include 'partials/footer' %}
{% include 'partials/footer' with ['links': links] %}
</div>
Incluir
include
has a special behavior that will help us improve performance a bit when using Volt, if you specify the extension when including the file, and it exists when the template is compiled, Volt can inline the contents of the template in the parent template where it’s included. Las plantillas no se incrustarán si el include
tiene variables pasadas con with
:
<div id='footer'>
{% include 'partials/footer.volt' %}
</div>
Parcial Vs Incluir
Tenga los siguientes puntos en mente cuando elija usar la función partial
o include
:
Tipo |
Descripción |
partial |
le permite incluir plantillas hechas en Volt y en otros motores de plantillas. También permite pasar de una expresión como una variable permitiendo incluir el contenido de otra vista dinámicamente. Es mejor si el contenido que usted tiene que incluir cambia con frecuencia |
include |
copia el contenido compilado en la vista, mejorando el rendimiento. Sólo permite incluir plantillas creadas con Volt. Requiere de una plantilla existente en tiempo de compilación |
Herencia
Con la herencia de plantillas puede crear plantillas base que pueden ser extendidas por otras plantillas, permitiéndole reutilizar código. A base template define blocks than can be overridden by a child template. Supongamos que tenemos la siguiente plantilla base:
{# templates/base.volt #}
<!DOCTYPE html>
<html>
<head>
{% block head %}
<link rel='stylesheet' href='style.css' />
{% endblock %}
<title>{% block title %}{% endblock %} - My Webpage</title>
</head>
<body>
<div id='content'>{% block content %}{% endblock %}</div>
<div id='footer'>
{% block footer %}
© Copyright 2012-present.
All rights reserved.
{% endblock %}
</div>
</body>
</html>
Desde otra plantilla podríamos extender la plantilla base reemplazando los bloques:
{% extends 'templates/base.volt' %}
{% block title %}Index{% endblock %}
{% block head %}<style>.important { color: #336699; }</style>{% endblock %}
{% block content %}
<h1>Index</h1>
<p class='important'>Welcome on my awesome homepage.</p>
{% endblock %}
No todos los bloques deben ser reemplazados en la plantilla hija, sólo aquellos que lo necesiten. La salida final producida será la siguiente:
<!DOCTYPE html>
<html>
<head>
<style>.important { color: #336699; }</style>
<title>Index - My Webpage</title>
</head>
<body>
<div id='content'>
<h1>Index</h1>
<p class='important'>Welcome on my awesome homepage.</p>
</div>
<div id='footer'>
© Copyright 2012-present.
All rights reserved.
</div>
</body>
</html>
Herencia múltiple
Las plantillas extendidas pueden extender otras plantillas. El ejemplo siguiente ilustra esto:
{# main.volt #}
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
La plantilla layout.volt
extiende main.volt
{# layout.volt #}
{% extends 'main.volt' %}
{% block content %}
<h1>Table of contents</h1>
{% endblock %}
Finally, a view that extends layout.volt
:
{# index.volt #}
{% extends 'layout.volt' %}
{% block content %}
{{ super() }}
<ul>
<li>Some option</li>
<li>Some other option</li>
</ul>
{% endblock %}
Al renderizar index.volt
produce:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Table of contents</h1>
<ul>
<li>Some option</li>
<li>Some other option</li>
</ul>
</body>
</html>
Fíjese en la llamada a la función super()
. Con esa función es posible renderizar los contenidos del bloque padre. Como parciales, la ruta establecida en extends
es una ruta relativa bajo el directorio actual de vistas (ej. app/views/
).
NOTE: By default, and for performance reasons, Volt only checks for changes in the children templates to know when to re-compile to plain PHP again, so it is recommended initialize Volt with the option 'always' => true
. Así, las plantillas se compilan siempre teniendo en cuenta los cambios en las plantillas padre.
Modo Autoescape
Puede habilitar el autoescape de todas las variables impresas en un bloque usando el modo autoescape:
Manually escaped: {{ invoice.inv_title|e }}
{% autoescape true %}
Autoescaped: {{ invoice.inv_title }}
{% autoescape false %}
No Autoescaped: {{ invoice.inv_title }}
{% endautoescape %}
{% endautoescape %}
Extender Volt
A diferencia de otros motores de plantillas, Volt en sí mismo no está obligado a ejecutar las plantillas compiladas. Una vez que se compilan las plantillas no hay ninguna dependencia con Volt. Con independencia del rendimiento en mente, Volt sólo actúa como un compilador de plantillas PHP.
El compilador de Volt permite ser ampliado, añadiéndole más funciones, tests o filtros a los ya existentes.
Funciones
Las funciones actúan como funciones normales de PHP, un nombre de cadena válida se requiere como nombre de la función. Las funciones se pueden agregar mediante dos opciones, retornando una cadena simple o utilizando una función anónima. Cualquiera que sea la opción que utilice, debe devolver una expresión de cadena de texto PHP válida.
El siguiente ejemplo vincula el nombre de función shuffle
en Volt a la función PHP str_shuffle
:
<?php
use Phalcon\Mvc\View\Engine\Volt;
$volt = new Volt($view, $container);
$compiler = $volt->getCompiler();
$compiler->addFunction('shuffle', 'str_shuffle');
y en Volt:
El ejemplo a continuación registra la función con una función anónima. Aquí usamos $resolvedArgs
para pasar los argumentos exactamente al llamar al método desde la vista:
<?php
$compiler->addFunction(
'widget',
function ($resolvedArgs, $exprArgs) {
return 'MyLibrary\Widgets::get(' . $resolvedArgs . ')';
}
);
y en Volt:
{{ widget('param1', 'param2') }}
También puede tratar los argumentos de forma independiente y también comprobar si hay parámetros sin resolver. En el ejemplo siguiente, recuperamos el primer parámetro y luego comprobamos la existencia de un segundo parámetro. Si está presente, lo almacenamos, de lo contrario usaremos el valor predeterminado 10
. Finally, we call the str_repeat
PHP method on the first and second parameter.
<?php
$compiler->addFunction(
'repeat',
function ($resolvedArgs, $exprArgs) use ($compiler) {
$firstArgument = $compiler->expression($exprArgs[0]['expr']);
if (isset($exprArgs[1])) {
$secondArgument = $compiler->expression($exprArgs[1]['expr']);
} else {
$secondArgument = '10';
}
return 'str_repeat(' . $firstArgument . ', ' . $secondArgument . ')';
}
);
y en Volt:
{{ repeat('Apples', 'Oranges') }}
También puede comprobar la disponibilidad de funciones en su sistema y llamarlas si está presente. En el siguiente ejemplo llamaremos a mb_stripos
si la extensión mbstring
está presente. Si está presente, entonces mb_stripos
será llamado, de lo contrario stripos
:
<?php
$compiler->addFunction(
'contains_text',
function ($resolvedArgs, $exprArgs) {
if (true === function_exists('mb_stripos')) {
return 'mb_stripos(' . $resolvedArgs . ')';
} else {
return 'stripos(' . $resolvedArgs . ')';
}
}
);
También puede sobreescribir funciones integradas usando el mismo nombre en la función definida. In the example below, we replace the built-in Volt function dump()
with PHP’s print_r
.
<?php
$compiler->addFunction('dump', 'print_r');
Filtros
Un filtro tiene la siguiente forma en una plantilla: leftExpr|name(optional-args)
. Agregar nuevos filtros es similar a lo visto en las funciones.
Añadir un nuevo filtro llamado hash
usando el método sha1
:
<?php
$compiler->addFilter('hash', 'sha1');
Añade un nuevo filtro llamado int
:
<?php
$compiler->addFilter(
'int',
function ($resolvedArgs, $exprArgs) {
return 'intval(' . $resolvedArgs . ')';
}
);
Los filtros incorporados se pueden reemplazar agregando una función con el mismo nombre. The example below will replace the built-in capitalize
filter with PHP’s lcfirst function:
<?php
$compiler->addFilter('capitalize', 'lcfirst');
Extensiones
Con las extensiones, el desarrollador tiene más flexibilidad para extender el motor de plantillas, y sobreescribir la compilación de instrucciones, cambiar el comportamiento de una expresión u operador, añadir funciones/filtros, y más.
Una extensión es una clase que implementa los eventos disparados por Volt como un método de sí mismo. Por ejemplo, la clase siguiente permite usar cualquier función PHP en Volt:
<?php
namespace MyApp\View\Extensions;
class PhpFunctionExtension
{
public function compileFunction(string $name, string $arguments)
{
if (true === function_exists($name)) {
return $name . '('. $arguments . ')';
}
}
}
La clase anterior implementa el método compileFunction
que se invoca antes de cualquier intento de compilar una llamada de función en cualquier plantilla. El propósito de la extensión es verificar si una función a compilar es una función PHP que permite llamar a la función PHP desde la plantilla. Los eventos en extensiones deben devolver código PHP válido, que se usará como resultado de la compilación en lugar del código generado por Volt. Si un evento no devuelve una cadena, la compilación se hace usando el comportamiento predeterminado proporcionado por el motor.
Las extensiones Volt se deben registrar en el compilador, haciéndolas disponibles en tiempo de compilación:
<?php
use MyApp\View\Extensions\PhpFunctionExtension;
$compiler->addExtension(
new PhpFunctionExtension()
);
Compilador
El compilador Volt depende del analizador Volt. El analizador analiza las plantillas Volt y crea una Representación Intermedia (IR) de ellas. El compilador usa esa representación y produce el código PHP compilado.
<?php
use Phalcon\Mvc\View\Engine\Volt\Compiler;
$compiler = new Compiler();
$compiler->compile("views/partials/header.volt");
require $compiler->getCompiledTemplatePath();
The Phalcon\Mvc\View\Engine\Volt\Compiler offers a number of methods that can be extended to suit your application needs.
public function __construct(ViewBaseInterface $view = null)
Constructor
public function addExtension(mixed $extension): Compiler
Registra una extensión
public function addFilter(
string $name,
mixed definition
): Compiler
Registra un nuevo filtro
public function addFunction(
string $name,
mixed $definition
): Compiler
Registra una nueva función
public function attributeReader(array $expr): string
Resuelve la lectura de atributos
public function compile(
string $templatePath,
bool $extendsMode = false
)
Compila una plantilla en un fichero aplicando las opciones del compilador. Este método no devuelve la ruta compilada si la plantilla no se compiló
$compiler->compile("views/layouts/main.volt");
require $compiler->getCompiledTemplatePath();
public function compileAutoEscape(
array $statement,
bool $extendsMode
): string
Compila una sentencia “autoescape” devolviendo código PHP
/**
* @deprecated Will be removed in 5.0
*/
public function compileCache(
array $statement,
bool $extendsMode = false
): string
(DEPRECATED) Compila una sentencia cache
devolviendo código PHP
public function compileCall(array $statement, bool $extendsMode)
Compila llamadas a macros
public function compileCase(
array $statement,
bool $caseClause = true
): string
Compila una cláusula case
/default
devolviendo código PHP
public function compileDo(array $statement): string
Compila una sentencia do
devolviendo código PHP
public function compileEcho(array $statement): string
Compila una sentencia {{
}}
devolviendo código PHP
public function compileElseIf(array $statement): string
Compila una sentencia elseif
devolviendo código PHP
public function compileFile(
string $path,
string $compiledPath,
bool $extendsMode = false
): string | array
Compila una plantilla en un fichero, también creando la ruta destino
$compiler->compileFile(
"views/layouts/main.volt",
"views/layouts/main.volt.php"
);
public function compileForeach(
array $statement,
bool $extendsMode = false
): string
Compila una sentencia foreach
devolviendo código PHP
public function compileForElse(): string
Compila una sentencia forelse
devolviendo código PHP
public function compileIf(
array $statement,
bool $extendsMode = false
): string
Compila una sentencia if
devolviendo código PHP
public function compileInclude(array $statement): string
Compila una sentencia include
devolviendo código PHP
public function compileMacro(
array $statement,
bool $extendsMode
): string
Compila una macro
public function compileReturn(array $statement): string
Compila una sentencia return
devolviendo código PHP
public function compileSet(array $statement): string
Compila una sentencia setter (asignación de valor a variable) devolviendo código PHP
public function compileString(
string $viewCode,
bool $extendsMode = false
): string
Compila una plantilla en una cadena
echo $compiler->compileString('{{ "hello world" }}');
public function compileSwitch(
array $statement,
bool $extendsMode = false
): string
Compila una sentencia switch
devolviendo código PHP
final public function expression(array $expr): string
Resuelve un nodo de expresión en un árbol AST de Volt
final public function fireExtensionEvent(
string $name,
array $arguments = null
)
public function functionCall(array $expr): string
Resuelve el código intermedio de funciones en llamadas a funciones PHP
public function getCompiledTemplatePath(): string
Devuelve la ruta a la última plantilla compilada
public function getExtensions(): array
Devuelve las extensiones registradas
public function getFilters(): array
Devuelve los filtros de usuario registrados
public function getFunctions(): array
Devuelve las funciones de usuario registradas
public function getOption(string $option): string
Devuelve una opción del compilador
public function getOptions(): array
Devuelve las opciones del compilador
public function getTemplatePath(): string
Devuelve la ruta que está siendo compilada actualmente
public function getUniquePrefix(): string
Devuelve un prefijo único a usar como prefijo de las variables y contextos compilados
public function parse(string $viewCode): array
Analiza una plantilla Volt devolviendo su representación intermedia
print_r(
$compiler->parse("{{ 3 + 2 }}")
);
public function resolveTest(array $test, string $left): string
Resuelve el código intermedio de filtro en una expresión PHP válida
public function setOption(string $option, mixed $value)
Establece una única opción del compilador
public function setOptions(array $options)
Establece las opciones del compilador
public function setUniquePrefix(string $prefix): Compiler
Establece un prefijo único a usar como prefijo de las variables compiladas
Eventos
Están disponibles los siguientes eventos de compilación para ser implementados en extensiones:
Evento/Método |
Descripción |
compileFunction |
Disparado antes de intentar compilar cualquier llamada de función en una plantilla |
compileFilter |
Disparado antes de intentar compilar ningún llamada de filtro en una plantilla |
resolveExpression |
Disparado antes de intentar compilar ninguna expresión. Esto permite al desarrollador sobreescribir operadores |
compileStatement |
Disparado antes de intentar compilar ninguna sentencia. Esto permite al desarrollador sobreescribir cualquier sentencia |
Servicios
Si un contenedor de servicios (DI) está disponible en Volt. Cualquier servicio registrado en el contendedor DI está disponible en Volt, con una variable del mismo nombre con el que está registrado el servicio. En el ejemplo siguiente usamos el servicio flash
, así como security
:
<div id='messages'>{{ flash.output() }}</div>
<input type='hidden' name='token' value='{{ security.getToken() }}'>
Independiente
Puede usar Volt como componente independiente en cualquier aplicación.
Registre el compilador y establezca algunas opciones:
<?php
use Phalcon\Mvc\View\Engine\Volt\Compiler as VoltCompiler;
$compiler = new VoltCompiler();
$compiler->setOptions(
[
// ...
]
);
Compilación de plantillas o cadenas:
<?php
echo $compiler->compileString(
"hello"
);
$compiler->compileFile(
'layouts/main.volt',
'cache/layouts/main.volt.php'
);
$compiler->compile(
'layouts/main.volt'
);
Finalmente puede incluir la plantilla compilada si es necesario:
<?php
require $compiler->getCompiledTemplatePath();
Compilar
Cada vez que despliega su aplicación a producción, necesitará eliminar los ficheros .volt
precompilados, para que se muestre cualquier cambio hecho en sus plantillas a los usuarios. Una forma muy fácil de hacer esto es limpiar la carpeta volt/
usando un script CLI o eliminar manualmente todos los ficheros.
Si asumimos que su ruta volt
se localiza en: /app/storage/cache/volt/
entonces el siguiente script le permitirá limpiar esa carpeta cada vez lo ejecute, normalmente después de un despliegue.
<?php
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use function in_array;
use function substr;
$fileList = [];
$whitelist = ['.', '..', '.gitignore'];
$path = appPath('storage/cache');
$dirIterator = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator(
$dirIterator,
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $file) {
if (true !== $file->isDir() &&
true !== in_array($file->getFilename(), $whitelist)) {
$fileList[] = $file->getPathname();
}
}
echo sprintf('Found %s files', count($fileList)) . PHP_EOL;
foreach ($fileList as $file) {
echo '.';
unlink($file);
}
echo PHP_EOL . 'Folder cleared' . PHP_EOL;
In the example above, we use PHP’s RecursiveDirectoryIterator and RecursiveIteratorIterator to iterate through a folder recursively and create a list of files in the $fileList
array. After that, we iterate through that array and unlink each file in turn.
Como hemos mencionado antes, basado en las opciones proporcionadas durante la configuración, Volt puede comprobar si los ficheros compilados existen y generarlos en consecuencia. Adicionalmente, Volt puede comprobar si los ficheros han cambiado, y en caso afirmativo regenerarlos.
Estas comprobaciones se realizan cuando las opciones always
y stat
están establecidas a true
. Para cualquier proyecto, comprobar el sistema de ficheros muchas veces por petición (una vez por fichero Volt), está consumiendo recursos. Adicionalmente, necesita asegurarse de que la carpeta usada para Volt para compilar las plantillas es escribible por su servidor web.
Puede crear un script o una tarea CLI (usando la Aplicación CLI) para compilar y guardar todos los ficheros cuando despliegue el código. De esta manera, será capaz de instruir a Volt que no compile o registre cada fichero por turno, incrementando el rendimiento. Adicionalmente, ya que estos ficheros se compilan durante el proceso de despliegue, la carpeta volt no necesitará ser escribible, incrementando la seguridad. Ya que las plantillas Volt compiladas son fragmentos phtml, no permitir al servidor web generar código ejecutable es siempre una buena idea.
Recuerde que este script será ejecutado en línea de comandos, pero para compilar nuestras plantillas necesitaremos arrancar nuestra aplicación web. En el ejemplo siguiente, necesitaremos obtener el contenedor DI que tiene todos los servicios registrados para nuestra aplicación web. Luego podemos usar el compilador Volt para compilar todas las plantillas a la carpeta correspondiente.
En el ejemplo siguiente, asumimos que tenemos una clase Bootstrap\Web
que es la responsable de configurar todos nuestros servicios para la aplicación Web. La clase devuelve el contenedor DI usando getContainer()
. Su implementación podría variar.
<?php
use MyApp\Library\Bootstrap\Web;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use function in_array;
use function substr;
if (php_sapi_name() !== "cli") {
throw new Exception(
'You need to run this script from the command line'
);
}
$bootstrap = new Web();
$container = $bootstrap->getContainer();
$view = $container->getShared('view');
$viewPath = $view->getViewsDir();
$volt = $container->getShared('volt');
$fileList = [];
$whitelist = ['.', '..', '.gitignore'];
$path = $viewPath;
$dirIterator = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator(
$dirIterator,
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $file) {
if (true !== $file->isDir() &&
true !== in_array($file->getFilename(), $whitelist)) {
$fileList[] = $file->getPathname();
}
}
echo sprintf('Found %s files', count($fileList)) . PHP_EOL;
foreach ($fileList as $file) {
echo '.';
$volt->getCompiler()->compile($file);
}
echo PHP_EOL . 'Templates compiled' . PHP_EOL;
Recursos externos
- Un paquete para Sublime/Textmate está disponible aquí
- Phosphorum, Phalcon’s forum implementation, also uses Volt, GitHub
- Vökuró, is another sample application that uses Volt, GitHub