Está en la página 1de 50

Taller de

Symfony
Clase 4
Roadmap

Helpers

Sesiones

Internacionalización

Modularización de las vistas
− Partials
− Components
Helpers

Son librerías de funciones que provee el
framework

Comúnmente estás funciones son utilizadas en
las vistas (templates) para generar links,
imprimir fechas con un formato específico,
incluir archivos, generar componentes HTML o
javascript, etc.

Es posible definir nuestros propios helpers con
funciones que querramos modularizar
− lib/helper/NombreHelper.php
Helpers (cont.)

Algunos helpers que provee el framework:
− JavascriptBase: Generar código Javascript

link_to_function(), button_to_function(), etc.
− Url: Generar links

link_to(), url_for(), public_path(), etc.

Durante el curso vamos a ir viendo más
helpers...
Helpers (cont.)

Si queremos utilizar las funciones de un Helper
en un template, debemos explícitamente indicar
que los queremos utilizar
<?php use_helper('Helper1','Helper2','HelperN') ?>

La función use_helper() está en un helper que
se llama “Helper”!!
− El framework siempre lo carga para poder
utilizarlo
Helpers (cont.)

Podemos indicar en un aplicación que queremos
contar con un conjunto de Helpers cargados por
defecto (y no hacer uso de la función
use_helper())
− apps/frontend/config/settings.yml
all:
.settings:
standard_helpers: [Partial, Cache]

Al igual que otros parámetros que hemos visto,
se pueden indicar por entorno de ejecución (all,
dev, prod, etc.)
Helpers (cont.)

Ya habíamos usado helpers!
− Cuando definimos el Layout de la aplicación

apps/frontend/templates/layout.php
− Usamos:

include_http_metas()

include_metas()

include_title()
− Estas funciones pertenecen a un helper “Asset”
que también carga siempre el framework
Helpers (cont.)

Veamos un ejemplo de una función en el helper
Asset para obtener un elemento html <img>
<div class="logo">
<?php echo image_tag('logo2.png',array('alt'=>'logo de
blogfony'));?>
</div>

• Solo debemos poner el nombre del archivo de la


imagen, automáticamente agrega la ruta para
localizar “web/images/”
• El arreglo permite pasar parámetros para el
elemento HTML (alt, size, etc).
Helpers (cont.)
• Veamos otro ejemplo de una función en el
helper “Text”, que permite cortar un texto a
una longitud que le indiquemos
− Lo usaremos para cortar el texto de un post,
cuando el mismo es muy largo
<?php use_helper('Text') ?>
......
<div class="text">
<?php echo truncate_text($post->getContent(), 50, '...')?>
</div>
.....
• Parámetros:
− El texto a cortar
− La longitud que deseamos
− El texto que queremos que aparezca al cortar
Helpers (ejemplo)
• Agregemos en el listado de posts, la accion ver
mas.
− Con un helper hacer un link que vaya a una pagina
donde nos muestre la información completa del
post.
− Como lo hacemos ?
Helpers (ejemplo)
• El template “indexSuccess.php”
<?php use_helper('Text', 'Url','I18N');?>
<h3>Ultimos Posts</h3>
<?php foreach($posts as $post):?>
<div class="list_post">
<div class="title">
<?php echo $post->getTitle();?>
<div class="date">
[<?php echo $post->getCreatedAt("d/m/Y h:i:s");?>]
</div>
</div>
<div class="text">
<?php echo truncate_text($post->getContent(), 50, '...'));?>
</div>
<div class="view-more">
<?php echo link_to(__('View more').' >>','main/viewPost?id='.
$post->getId())?>
</div>
</div>
<?php endforeach;?>
Helpers (ejemplo)
• Obtenemos el post cuyo id se paso por
parametro
public function executeViewPost(sfWebRequest $request)
{
$post_id = $request->getParameter('id');
$this->post = PostTable::getInstance()->find($post_id);
}

• PostTable::getInstance()->find($post_id), retorna una


instancia de post cuyo id sea igual al pasado por
parametro.
Helpers (ejemplo)
• Agregamos el template viewPostSuccess.php
<?php use_helper('I18N', 'Date') ?>

<div id="sf_admin_container">
<h2><?php echo $post->getTitle() ?></h2>

<div id="sf_admin_content">
<div class="sf_admin_form">
<fieldset id="sf_admin_fieldset_none">
<div class="sf_admin_form_row">
<label><?php echo __("Content") ?></label>
<div class="content">
<?php echo $post->getContent() ?>
</div>
</div>
<div class="sf_admin_form_row">
<label><?php echo __("Calification sum") ?></label>
<div class="content">
<?php echo $post->getCalificationSum() ?>
</div>
</div>
Helpers (ejemplo)
<div class="sf_admin_form_row">
<label><?php echo __("Calification count") ?></label>
<div class="content">
<?php echo $post->getCalificationCount() ?>
</div>
</div>
</fieldset>
</div>
</div>
</div>
Helpers (ejemplo)

Probemos el ver más >>
− Veamos como queda si intentamos ver un post!
La sesión

symfony encapsula la sesión del usuario en una
clase

La clase está definida en el directorio “lib” de
cada aplicación
− apps/frontend/lib/myUser.class.php

Está clase es sub-clase de una clase del
framework: sfBasicSecurityUser
class myUser extends sfBasicSecurityUser
{
}
La sesión (cont.)

Brinda un conjunto de métodos para guardar y
obtener datos de la sesión
− setAttribute($name,$value)
− getAttribute($name,$default=null)
− hasAttribute($name)
• Desde una acción podemos obtener el usuario
con el método getUser()
$this->getUser()
• Desde un template, podemos usar el usuario
directamente con una variable que siempre
existe
$sf_user
I18Nternacionalización
• symfony provee un mecanismo para hacer
aplicaciones internacionalizadas
− Mismas acciones, mismos templates, se ajustan
al lenguaje que el usuario quiere
• Es posible internacionalizar las vistas y los datos
− En el curso solo veremos como internacionalizar
las vistas
• El usuario tiene una cultura, y en función de ella
de define el idioma a utilizar o la forma de
imprimir números, fechas, etc.
− es_AR, en_US, en_EN
I18Nternacionalización (cont.)

Para hacer que el texto que aparece en las vistas
sea internacionalizable debemos imprimirlo
utilizando una función
− __() (doble guión bajo)

Está función pertenece a un helper que se llama
I18N, por lo que debemos incluirlo (en cada
template) o agregarlo por defecto
use_helper('I18N')

all:
.settings:
standard_helpers: [Partial, Cache, I18N]
I18Nternacionalización (cont.)

Debemos definir el archivo de diccionario para
cada cultura, donde para cada palabra
indicamos la traducción según la cultura
− Deberá existir un archivo por cada lenguaje que
realizamos la traducción
− Los diferentes archivos se ubican en

apps/<app-name>/i18n
− Cada archivo se debe llamar

messages.LANG.xml

donde LANG es: es, en, fr, etc.
I18Nternacionalización (cont.)
apps/frontend/i18n/messages.es.xlm
<?xml version="1.0" ?>
<xliff version="1.0">
<file original="global" source-language="en_US"
datatype="plaintext">
<body>
<trans-unit id="1">
<source>Content</source>
<target>Contenido</target>
</trans-unit>
<trans-unit id="2">
<source>View More</source>
<target>Ver Mas</target>
</trans-unit>
</body>
</file>
En recursos adicionales hay un archivo para el blog
</xliff>
I18Nternacionalización (cont.)

Debemos activar I18N en la aplicación para que
el framework realice las traducciones
− apps/frontend/settings.yml
all:
.settings:
i18n: on

Para indicar que cultura queremos utilizar,
podemos hacerlo por defecto para la aplicación
all:
.settings:
default_culture: es
I18Nternacionalización (cont.)

Existe un comando muy útil que a partir de
todos los templates y partials generados que
utilizan internacionalización, genera el
archivo .xml de internacionalización para un
idioma dado y una aplicación dada.

Genera el archivo de internacionalización con
todos los strings que estan entre __() en los
templates y partials.
symfony i18n:extract --auto-save frontend es
I18Nternacionalización (cont.)

También podemos hacerlo dinámicamente
utilizando el usuario (ej: desde una acción)
− setCulture($cultura)
$this->getUser()->setCulture("es_AR");

Es posible consultar la cultura que tiene el
usuario (ej: desde una acción)
$this->getUser()->getCulture();
• Hint: Si hacemos estos cambios y ya teníamos
abierto el blog, debemos cerrar el navegador y
volver a abrirlo para que se inicie una nueva sesión
I18Nternacionalización (cont.)
• Cambiemos algunos templates que hemos
realizado para ver I18N en acción!
− apps/frontend/modules/main/templates/indexS
uccess.php
<h3><?php echo __('Latest Post');?></h3>

<?php echo __('View More');?>

− apps/frontend/templates/layout.php
<?php echo __('Register');?>
<?php echo __('New Post');?>
<?php echo __('Login');?>
I18Nternacionalización (cont.)
• Es posible internacionalizar también el formato
de las fechas, números, etc. según la cultura
− format_number($num) (helper Number)
− format_currency($num) (helper Number)
− format_date ($time) (helper Date)
− format_datetime($time) (helper Date)
− format_country($cult) (helper I18N)
• Veamos un ejemplo con la fecha del Post
− apps/frontend/modules/main/templates/index.
php
<?php use_helper('Date');?>
....
[<?php echo format_datetime($post->getCreatedAt());?>]
Modularización de vistas
Partials

Fragmentos de código de templates

Podemos reutilizarlos en diferentes templates


Se definen en los directorios /templates
− De cada módulo o el global de la aplicación

El nombre del archivo debe comenzar con
“_partialName”
Modularización de vistas
Partials (cont.)

Es posible incluir un partial de:
− El mismo módulo del cual se realiza la inclusión
− De otro módulo, diferente al cual se realiza la
inclusión
− Del directorio de templates global de la
aplicación (apps/<app-name>/templates)

Existe una función helper para incluirlos
− include_partial(“partialName”);

Sin el “_”
Modularización de vistas
Partials (cont.)

Ejemplos:
//Incluir un partial del mismo módulo del
//template que lo incluye
<?php include_partial("partialName");?>

//Incluir un partial de otro módulo al


//del template que lo incluye
<?php include_partial("moduleName/partialName");?>

//Incluir un partial global, del directorio de


//templates de la aplicación
<?php include_partial("global/partialName");?>
Modularización de vistas
Partials (cont.)

Refactorizando el layout.php
− apps/frontend/templates/layout.php
...
<body>
<div id="wrapper">
<?php include_partial("global/header")?>
<div id="container">
<?php include_partial("global/left")?>
<div id="content">
<?php echo $sf_content ?>
</div>
<?php include_partial("global/right")?>
</div>
<?php include_partial("global/footer")?>
</div> <!-- end content-wrapper -->
</body>
...
Modularización de vistas
Partials (cont.)

Refactorizando el layout.php (cont.)
− apps/frontend/templates/_right.php
<div id="right">
<h2>Top Tags</h2>
</div><!-- end container-right -->

− apps/frontend/templates/_left.php
<div id="left">
<h2>Top Posts</h2>
</div><!-- end container-left -->

− apps/frontend/templates/_footer.php
<div id="footer">
2010 | BlogFony
</div>
Modularización de vistas
Partials (cont.)

Refactorizando el layout.php (cont.)
− apps/frontend/templates/_header.php
<div id="header">
<div class="logo">
<?php echo image_tag('logo2.png',array('alt'=>'logo de blogfony'));?>
</div>
<div class="navigation">
<div class="top_navigation"><a href="#">Login</a></div>
<div class="top_navigation"><a href="#"><?php echo __('Register');?
></a></div>
<div class="top_navigation"><a href="#"><?php echo __('New Post');?
></a></div>
</div>
<form class="search">
<input type="text" name="q" value="<?php echo __('search');?>..."
id="q" onFocus="this.select()"/>
<input type="submit" value="" id="search"/>
</form>
<h1>blog symfony</h1>
</div> <!-- end header -->
Modularización de vistas
Partials (cont.)

Es posible pasarle parámetros a los partials
<?php include_partial("name",array('param1'=>'value1',
'paramN'=>'valueN'))?>


Dentro de los partials, podemos usar los
parámetros como variables
<?php echo $param1; ?>
<?php echo $paramN->getName(); ?>
Modularización de vistas
Partials (cont.)

Mostrando los tags de un post
− Creamos el partial que los mostrará

apps/fronend/modules/main/templates/_tags.ph
p
<div class="tags">
<?php foreach ($post->getPostTag() as $post_tag): ?>
<div class="tag"> <?php echo $post_tag->getTag() ?> </div>
<?php endforeach ?>
</div>
− Consideraciones

El partial recibe un parámetro que se llama “post”

El clase “Post” tiene un método para obtener los
objetos “PostTag” relacionados

Se imprime directamente el tag (->getTag())
Modularización de vistas
Partials (cont.)
Antes de continuar, agreguemos Tags a los Posts
 data/fixtures/01-tags.yml
Tag:
<?php for ($i = 1; $i <= 30; $i++): ?>
tag_<?php echo $i ?>:
name: Etiqueta <?php echo $i."\n" ?>
<?php endfor ?>

 data/fixtures/03-post_tag.yml
PostTag:
<?php for ($i = 1; $i < 50; $i++): ?>
post_tag_<?php echo $i ?>:
Post: post_<?php echo ((($i + 50) % 20) + 1)."\n" ?>
Tag: tag_<?php echo ((($i + 50) % 30) + 1)."\n" ?>
<?php endfor ?>
Modularización de vistas
Partials (cont.)

Mostrando los tags de un post (cont.)
− Modifiquemos el template del post para incluir el
partial “_tags”
...
<div class="text">
<?php echo truncate_text($post->getContent(),50,'...') ;?>
</div>
<?php echo include_partial('tags',array('post'=>$post));?>
<div class="view-more">
<?php echo link_to(__('View more').' >>','main/viewPost?id='.
$post->getId())?>
</div>
...
− Veamos como queda!

Opps!!!! Fatal error!
Modularización de vistas
Partials (cont.)

Mostrando los tags de un post (cont.)
− Al querer imprimir un Tag nos dice que la clase
no tiene el método “__toString()”
− Agreguemos el método

lib/model/doctrine/Tag.php

class Tag extends BaseTag


{
public function __toString()
{
return $this->getName();
}
}
− Ahora si, veamos como queda!
Modularización de vistas
Components

Se apoya en el concepto MVC: separar la lógica
de las vistas

En ocasiones, es necesario realizar incluir un
partial que contenga “lógica”
− Como sí fuera una acción y su template
Modularización de vistas
Components (cont.)

Se almacenan en archivos
“components.class.php” dentro del modulo
− apps/<app-name>/modules/<module>/actions

Son clases que heredan de sfComponents
− class moduleNameComponents extends sfComponents

La lógica se escribe en un método de la clase
− executeComponentOne()

La vista se escribe en partials
− _componentOne.php
Modularización de vistas
Components (cont.)

Generemos un component para mostrar el “Top
Ten” de Posts (los más votados!)
− apps/frontend/modules/main/actions/components.class.
php
class mainComponents extends sfComponents
{
public function executePostTopTen(){
$this->post = PostTable::doSelectTopTen(
sfConfig::get("app_max_posts_topten",10)
);
}
}
− Antes de hacer la vista para el componente,
agreguemos el método “doSelectTopTen” a la clase
PostTable
Modularización de vistas
Components (cont.)

Pensemos como sería el SQL para mostrar
obtener los 10 Post más votados
SELECT *
FROM post
ORDER BY (calification_sum / calification_count) DESC
LIMIT 10

Realicemos el método
− lib/model/doctrine/PostTable.php
public static function doSelectTopTen($max = 10)
{
$q = Doctrine_Query::create()->from('Post p')
->addOrderBy(“p.CALIFICATION_SUM / p.CALIFICATION_COUNT
DESC”)->limit($max);
return $q->execute();
}
Modularización de vistas
Components (cont.)
• Volvamos al Component, y hagamos la vista
correspondiente!
− apps/frontend/modules/main/templates/_postTopTe
n.php
<ul class="navi">
<?php foreach ($posts as $post):?>
<li>
<?php echo $post->getTitle();?>
</li>
<?php endforeach;?>
</ul>
− No nos olvidemos del parámetro “max_posts_topten”
 apps/frontend/config/app.yml
all:
max_posts_homepage: 10
max_posts_topten: 10
Modularización de vistas
Components (cont.)

Por ultimo, hagamos aparecen el componente a
la izquierda del blog!
− apps/frontend/templates/_left.php

<div id="left">
<h2>Top Post</h2>
<?php include_component('main','postTopTen');?>
</div><!-- end content-LEFT -->

− Veamos como queda!


Modularización de vistas
Components (cont.)
Modularización de vistas
Components (cont.)

Generemos otro Component para mostrar el
“Top Ten” de Tags (que tienen mas Posts)
− apps/frontend/modules/main/actions/components.class.p
hp
...
public function executeTagsTopTen(){
$this->post_tags = PostTagTable::doSelectTopTen(
sfConfig::get("app_max_tag_topten",10)
);
}
...

− Antes de hacer la vista para el componente,


agreguemos el método “doSelectTopTen” a la clase
TagTable
Modularización de Vistas
Components (cont.)

Agreguemos el parámetro al app.yml
− apps/frontend/config/app.yml
all:
max_post_homepage: 10

Realicemos el 10
max_post_topten: método
max_tag_topten: 10
− lib/model/PostTagTable.php
public static function doSelectTopTen($max = 10)
{
$q = Doctrine_Query::create()
->from('PostTag p')
->addOrderBy("COUNT(p.POST_ID) DESC")
->limit($max);

return $q->execute();
}
Modularización de vistas
Components (cont.)

Volvamos al Component, y hagamos la vista
correspondiente!
− apps/frontend/modules/main/templates/_tagsTopTen
.php

<ul class="navi">
<?php foreach ($post_tags as $post_tag): ?>
<li>
<?php echo $post_tag->getTag()->getName() ?>
(<?php echo count($post_tag->getPost()) ?>)
</li>
<?php endforeach ?>
</ul>
Modularización de vistas
Components (cont.)

Por ultimo, hagamos aparecen el componente a
la izquierda del blog!
− apps/frontend/templates/_right.php

<div id="right">
<h2>Top Tags</h2>
<?php include_component('main','tagsTopTen');?>
</div><!-- end content-RIGHT -->

− Veamos como queda!


Modularización de vistas
Components (cont.)
Fin de la clase

¿Consultas?

También podría gustarte