Entradas etiquetadas con vista
Symfony: La vista (IV), mecanismo de escape
0Este capítulo del libro me está resultando de lo más pesado, principalmente porque no hay mucho con lo que practicar, ya que la mayoría de la información es teoría basada en donde ubicar cada cosa en cada caso. Aunque las posibilidades que ofrece Symfony a medida que te adentras en él, son enormes.
Para acabar con la vista solo queda ver el mecanismo de escape que utiliza Symfony. Empezemos:
Este apartado del libro comienza así:
Cuando se insertan datos generados dinámicamente en una plantilla, se debe asegurar la integridad de los datos. Por ejemplo, si se utilizan datos obtenidos mediante formularios que pueden rellenar usuarios anónimos, existe un gran riesgo de que los contenidos puedan incluir scripts y otros elementos maliciosos que se encargan de realizar ataques de tipo XSS (cross-site scripting). Por tanto, se debe aplicar un mecanismo de escape a todos los datos mostrados, de forma que ninguna etiqueta HTML pueda ser peligrosa.
ACTIVANDO EL MECANISMO DE ESCAPE
Fácil. El mecanismo de escape se activa en el archivo config/settings.yml de la aplicación utilizando para ello dos parámentros:
- scaping_strategy: Define la forma en la que las variables están disponibles en la vista.
- scaping_method: Indica la función que se aplica a los datos.
all:
.settings:
escaping_strategy: both
escaping_method: ESC_ENTITIES
Esto de aquí arriba es lo único que tendrás que escribir para activar el mecanismo de escape. Ahora mismo, nuestra aplicación estaría utilizando el método htmlentities() de PHP para escapar los caracteres de html. Más adelante veremos más valores que pueden tener estos parámentros.
Por ejemplo, si tenemos en nuestra acción esta variable:
$this->prueba = ‘<script>alert(document.cookie)</script>’;
Al tener el mecanismo de escape activado, al mostrarla en la plantilla nos dará el siguiente resultado:
echo $prueba;
=> ><script>alert(document.cookie)</script>
Si se activa el mecanismo de escape, desde cualquier plantilla se puede acceder a una nueva variable llamada $sf_data. Se trata de un objeto contenedor que hace referencia a todas las variables que se han modificado mediante el sistema de escape. De esta forma, también es posible mostrar el contenido de la variable prueba de la siguiente manera:
echo $sf_data->get(‘prueba’);
=> ><script>alert(document.cookie)</script>
Con esta clase también podemos acceder a los datos de la variable en crudo, es decir, antes de que sus caracteres fuesen escapados:
echo $sf_data->getRaw(‘prueba’);
=> <script>alert(document.cookie)</script>
OPCIONES PARA scaping_strategy
- backward compatible mode (o modo retrocompatible): el contenido de las variables no se modifica, pero el contenedor $sf_data almacena una versión modificada de cada variable. De esta forma, los datos de las variables se obtienen en crudo, a menos que se obtenga la versión modificada del objeto $sf_data. Se trata del valor por defecto de la opción, aunque se trata del modo que permite los ataques de tipo XSS.
- both: a todas las variables se les aplica el mecanismo de escape. Los valores también están disponibles en el contenedor $sf_data. Se trata del valor recomendado, ya que solamente se está expuesto al riesgo si se utilizan de forma explícita los datos originales. En ocasiones, se deben utilizar los valores originales, por ejemplo para incluir código HTML de forma que se interprete en el navegador y no se muestre el código HTML. Si una aplicación se encuentra medio desarrollada y se cambia la estrategia del mecanismo de escape a este valor, algunas funcionalidades pueden dejar de funcionar como se espera. Lo mejor es seleccionar esta opción desde el principio.
- on: los valores solamente están disponibles en el contenedor $sf_data. Se trata del método más seguro y más rapido de manejar el mecanismo de escape, ya que cada vez que se quiere mostrar el contenido de una variable, se debe elegir el método get() para los datos modificados o el método getRaw() para el contenido original. De esta forma, siempre se recuerda la posibilidad de que los datos de la variable sean corruptos.
- off: deshabilita el mecanismo de escape. Las plantillas no pueden hacer uso del contenedor $sf_data. Si nunca se va a necesitar el sistema de escape, es mejor utilizar esta opción y no la opción por defecto bc, ya que la aplicación se ejecuta más rápidamente.
OPCIONES PARA scaping_method
- ESC_RAW: no modifica el valor original.
- ESC_ENTITIES: aplica la función htmlentities() de PHP al valor que se le pasa y utiliza la opción ENT_QUOTES para el estilo de las comillas.
- ESC_JS: modifica un valor que corresponde a una cadena de JavaScript que va a ser utilizada como HTML. Se trata de una opción muy útil para escapar valores cuando se emplea JavaScript para modificar de forma dinámica el contenido HTML de la página.
- ESC_JS_NO_ENTITIES: modifica un valor que va a ser utilizado en una cadena de JavaScript pero no le añade las entidades HTML correspondientes. Se trata de una opción muy útil para los valores que se van a mostrar en los cuadros de diálogo (por ejemplo para una variable llamada miCadena en la instrucción javascript:alert(miCadena);).
APLICANDO EL MECANISMO DE ESCAPE A ARRAYS Y OBJETOS
// Definición de la clase
class miClase
{
public function pruebaCaracterEspecial($valor = »)
{
return ‘<‘.$valor.’>’;
}
}// En la acción
$this->array_prueba = array(‘&’, ‘<‘, ‘>’);
$this->array_de_arrays = array(array(‘&’));
$this->objeto_prueba = new miClase();// En la plantilla
<?php foreach($array_prueba as $valor): ?>
<?php echo $valor ?>
<?php endforeach; ?>
=> & < >
<?php echo $array_de_arrays[0][0] ?>
=> &
<?php echo $objeto_prueba->pruebaCaracterEspecial(‘&’) ?>
=> <&>
Los métodos de los objetos a los que se aplica el mecanismo de escape aceptan un parámetro adicional:
<?php echo $objeto_prueba->pruebaCaracterEspecial(‘&’) ?>
=> <&>
// Las siguientes 3 líneas producen el mismo resultado
<?php echo $objeto_prueba->pruebaCaracterEspecial(‘&’, ESC_RAW) ?>
<?php echo $sf_data->getRaw(‘objeto_prueba’)->pruebaCaracterEspecial(‘&’) ?>
<?php echo $sf_data->get(‘objeto_prueba’, ESC_RAW)->pruebaCaracterEspecial(‘&’) ?>
=> <&>
Las variables de Symfony también se modifican al activar el mecanismo de escape. Por tanto, las variables $sf_user, $sf_request, $sf_param y $sf_context siguen funcionando, pero sus métodos devuelven sus datos modificados, a no ser que se utilice la opción ESC_RAW como último argumento de las llamadas a los métodos.
Symfony: La vista (I), fragmentos de código
0Debido a que la parte de Symfony que explicaré hoy es bastante densa no podré resumir en un solo post todo el capítulo referente a la Vista, por tanto este será el primero de una serie de post sobre la Vista en Symfony que se explica en el manual de Symfony.
La vista
Como ya he comentado en anteriores post, Symfony sigue el sistema de Modelo-Vista-Controlador (MVC) para que la realización de nuestros proyectos estén mucho mejor estructurados y sean más fáciles de comprender por otros programadores.
Symfony para crear las vistas o implementar el diseño que hemos creado a nuestro proyecto, utiliza plantillas, esto son trozos de código html que se unen para formar la página que ha pedido el usuario.
En Symfony todo el diseño se divide de la siguiente manera:
- Layout: Es la parte del diseño que se mostrará en todas las páginas (cabeceras, pie, menú, etc).
- Elementos parciales: Si el fragmento contiene poca lógica.
- Componentes: Si el fragmento tiene mucha lógica o debe acceder a la base de datos.
- Slots: Si el fragmento va a sustituir a una parte del layout y se mostrará una parte por defecto.
En el libro lo explican bastante bien como se dividen las plantillas, los fragmentos de código que se pueden utilizar, cómo pasar variables desde la acción a los fragmentos de código, y algún detalle más que viene bien conocer. Os dejo el link a los Fragmentos de código.
Normalmente cuando trabajamos con plantillas en nuestros proyectos PHP, utilizamos la instrucción include() y en Symfony podríamos añadir a nuestro código algo como lo siguiente:
<?php include(sfConfig::get(‘sf_app_template_dir’).’/miFragmento.php’) ?>
Pero esta forma de añadir fragmentos de código no es muy limpia y, además, la caché de Symfony no reconoce la instrucción include() con lo que ese fragmento no podría ser cacheado. Aquí es donde entran en juego los fragmentos de código que he comentado anteriormente.
ELEMENTOS PARCIALES
Observa un periódico digital, su portada concretamente, verás que las noticias estan encajadas como en recuadros imaginarios y que cada noticia sigue un patrón: un titular y un pequeño avance de la noticia. Eso es un elemento parcial. Podemos poner ese elemento parcial en cualquier parte de ese periódico digital, ya que siempre será importante que el usuario pueda acceder a otras noticias con un pequeño avance.
Symfony sigue esta misma lógica para los elementos parciales. Estos, al igual que las plantillas, se ubican en la carpeta «templates/» del proyecto y son accesibles desde el módulo en el que se encuentre el archivo, desde otro módulo o desde la carpeta raíz de las plantillas «templates/«. Los elementos parciales se diferencian de las plantillas por llevar un guión bajo al principio del nombre del archivo ( _elementoparcial.php). Veamos como llamar a los elementos parciales desde distintas ubicaciones:
// Incluir el elemento parcial de miaplicacion/modules/mimodulo/templates/_miparcial1.php
// Como la plantilla y el elemento parcial están en el mismo módulo,
// se puede omitir el nombre del módulo
<?php include_partial(‘miparcial1’) ?>// Incluir el elemento parcial de miaplicacion/modules/otromodulo/templates/_miparcial2.php
// En este caso es obligatorio indicar el nombre del módulo
<?php include_partial(‘otromodulo/miparcial2’) ?>// Incluir el elemento parcial de miaplicacion/templates/_miparcial3.php
// Se considera que es parte del módulo ‘global’
<?php include_partial(‘global/miparcial3’) ?>
PASANDO VARIABLES AL ELEMENTO PARCIAL
Primero definimos la variable en la acción del módulo llamado mimodulo (mimodulo/actions/actions.class.php)
class mimoduloActions extends sfActions
{
public function executeIndex()
{
$this->total = 100;
}
}
En la plantilla llamamos al elemento parcial con la función include_partial() y le pasamos la variable en mimodulo/templates/indexSuccess.php.
<p>¡Hola Mundo!</p>
<?php include_partial(‘miparcial’, array(‘mitotal’ => $total)
) ?>
De esta manera podremos usar la variable en el elemento parcial en mimodulo/templates/_miparcial.php.
<p>Total: <?php echo $mitotal ?></p>
COMPONENTES
Los componentes son como los módulos, pero más rápidos. Siguen la misma lógica que los módulos y tienen una estructura de archivos parecida. Para nombrar un componente se utiliza la palabra execute seguido del nombre del componente, por ejemplo:
La clase de los componentes, en modules/news/actions/components.class.php
<?php
class newsComponents extends sfComponents
{
public function executeHeadlines()
{
$c = new Criteria();
$c->addDescendingOrderByColumn(NewsPeer::PUBLISHED_AT);
$c->setLimit(5);
$this->news = NewsPeer::doSelect($c);
}
}
La parte visual de los componentes se crea utilizando los elementos parciales. Para nombrarlos se usa lo mismo que para los componentes solo que sustituyendo la palabra execute por un guión bajo.
El elemento parcial, en modules/news/templates/_headlines.php
<div>
<h1>Últimas noticias</h1>
<ul>
<?php foreach($news as $headline): ?>
<li>
<?php echo $headline->getPublishedAt() ?>
<?php echo link_to($headline->getTitle(),’news/show?id=’.$headline->getId()) ?>
</li>
<?php endforeach ?>
</ul>
</div>
Cada vez que se quiera añadir el componente a una plantilla, sólo será necesario escribir el siguiente código:
<?php include_component(‘news’, ‘headlines’) ?>
Paso de parámetros a un componente y su plantilla:
// Llamada al componente
<?php include_component(‘news’, ‘headlines’, array(‘parametro’ => ‘valor’)) ?>// Dentro del componente
echo $this->parametro;
=> ‘valor’// Dentro del elemento parcial _headlines.php
echo $parametro;
=> ‘valor’
SLOTS
Aquí debería hablaros de los slots que simplemente son una especie de elemento parcial configurable, y para explicároslo solo se me ocurre hacer un copy&paste del libro, así que os dejo el link (al final de la página) y espero que os ayude.