Mi primer proyecto

Este tutorial es una interpretación al castellano del siguiente:
Symfony tutorial My first symfony project, que plantea hacer una pequeña aplicación en una hora, que consiste en un miniblog. Vamos a ver si nos alcanza el tiempo.
En el artículo original usan Sqlite como base de datos, que viene incluida y compilada por defecto en PHP5 no así en PHP5.1.0 y sugieren activarla así, pero nosotros venimos de instalar WAMP, así que vamos a usar Mysql, con Apache y PHP5, pero esto no implica ninguna diferencia en el proceso, así que pueden hacerlo con la base de datos que prefieran.

Instalar Symfony e inicializar el proyecto

La manera mas rápida (y que no necesita la instalación de Symfony) es usar el sandbox de Symfony, que es un proyecto de Symfony vacío con todas las librerías necesarias ya incluidas y con la configuración básica hecha. La ventaja de esto es que podes empezar a experimentar con Symfony rápidamente, sin necesidad de instalarlo.
Descargar el archivo sf_sandbox.tgz en el directorio Web, se puede encontrar mas información en el archivo readme que viene incluido. La estructura resultante se ve así:

www/
  sf_sandbox/
    apps/
      frontend/
    batch/
    cache/
    config/
    data/
      sql/
    doc/
    lib/
      model/
    log/
    plugins/
    test/
    web/
      css/
      images/
      js/

Nosotros ya instalamos Symfony, así que vamos a abrir la consola y vamos a ejecutar los siguientes comandos para crear nuestro proyecto:

mkdir wamp/www/miniblog
cd wamp/www/miniblog
symfony new miniblog
symfony app frontend

Para verificar la instalación, vemos la siguiente URL:
http://localhost/miniblog/web (o http://localhost/sf_sandbox/web en el caso de que se este trabajando con el sandbox, nosotros de acá en más nos vamos a referir a miniblog). Deberíamos ver la siguiente pantalla:

Te puede pasar que no veas los estilos y las imágenes, solo el contenido. Esto se debe a que para mostrar las páginas por defecto Symfony usa sus propias librerías, para acceder a ellas hay que configurar un alias en el servidor Apache, pero en nuestro caso solo vamos a copiar el directorio C:\wamp\bin\php\php5.2.5\PEAR\data\symfony\web\sf a C:\wamp\www\miniblog\web, que es la manera mas rápida. La guía definitiva de Symfony contiene mas información sobre la instalación, configuración del servidor (alias y Virtual host) y estructura de directorios.

Inicializar el modelo de datos

Todo blog que se precie de tal tiene artículos (aunque sea "mini") sobre los cuales se puede comentar, entonces creamos el siguiente modelo de datos en el archivo schema.yml del directorio /miniblog/config/

propel:
  miniblog_articulo:
    _attributes: { phpName: Articulo }
    id:
    titulo:     varchar(255)
    resumen:    longvarchar
    contenido:  longvarchar
    created_at:
  miniblog_comentario:
    _attributes: { phpName: Comentario }
    id:
    articulo_id:
    autor:      varchar(255)
    email:      varchar(255)
    contenido:  longvarchar
    created_at:

Este archivo de configuración usa la sintaxis YAML. Es un lenguaje muy simple que permite hacer estructuras tipo árbol por indentación, por lo que es más simple de leer y escribir que el XML. Pero es muy importante tener en cuenta la indentación, las tabulaciones están prohibidas, solo permite usar espacios, y cada espacio tiene un significado.
Se puede ver mas sobre archivos YAML en el capitulo de configuración del manual.
Este esquema representa la estructura de las dos tablas que necesitamos para un blog, Articulo y Comentario son los nombre de las clases relacionadas que se van a generar.
Antes de generar las clases que planteamos en el modelo anterior vamos a retocar otro archivito YAML para configurar el proyecto para que trabaje con Mysql. Abrimos el archivo databases.yml del directorio miniblog/config y le agregamos lo siguiente:

all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://usuario:contraseña@localhost/miniblog

Es necesario cambiar el archivo miniblog/config/propel.ini y configurar el el los datos de conexión a la base de datos, las lineas:

propel.database.createUrl  = mysql://usuario:contraseña@localhost/
propel.database.url        = mysql://usuario:contraseña@localhost/miniblog

No olvidar crear la base de datos miniblog en mysql.
Una vez guardados los archivos, abrir una consola, ubicarse en el directorio /miniblog y tipear los siguiente comando:

symfony propel-build-all

Este comando agrupa y reemplaza tres pasos en uno:
propel-build-model -> Genera el modelo, en el directorio miniblog/lib/model agrega las clases que nos permiten acceder a la base de datos sin usar sentencias Sql. Ver mas en el capítulo El modelo del manual.
propel-build-sql -> Crea el archivo miniblog/data/sql/lib.model.schema.sql, en base a la estructura que definimos antes, listo para ser insertado en nuestra base de datos.
propel-insert-sql -> Inserte el archivo generado en el paso anterior en nuestra base de datos.

Crear la interfase de nuestra aplicación web

En nuestro miniblog se debe poder agregar, mostrar, editar y borrar artículos y comentarios, para esto vamos a utilizar un generador CRUD (create, retrieve, update and delete) que puede interpretar el modelo y generar la interfase automáticamente. En consola, siempre ubicados en el directorio de nuestro blog, tipeamos:

symfony propel-generate-crud frontend articulo Articulo
symfony propel-generate-crud frontend comentario Comentario

Ya tenemos creados dos módulos (Articulo y Comentarios) con sus clases. Un módulo representa una página o grupo de páginas con un propósito similar. Los módulos creados están en miniblog/apps/frontend/modules/ y podemos acceder a ellos desde las siguientes URLs:
http//localhost/miniblog/web/frontend_dev.php/articulo
http//localhost/miniblog/web/frontend_dev.php/comentario
Ahora podemos cargar algunos artículos para que no se vea tan vacío...
Se puede encontrar mas información sobre interfase y la estructura del proyecto en el manual.

En las URL que llamamos antes, cambiamos el index.php (llamado controlador frontal en Symfony) por el frontend_dev.php. Las dos URL acceden a la misma aplicación pero lo que cambia es el entorno. Con el segundo entramos en el entorno de desarrollo, con el primero al entorno de producción, que nos da algunas herramientas e información útil. Este entorno no guarda el cache lo que lo hace mas lento pero útil en la etapa de desarrollo, que necesitamos probar modificaciones constantemente. Si prefieren usar el entorno de producción, no olviden limpiar el cache luego de hacer una modificación en la configuración, con el comando symfony cc

Se puede ver mas sobre entornos en el manual.

Modificar el Layout

Para poder navegar en las dos interfases de los diferentes módulos, nuestro miniblog necesita una navegación global. Vamos a editar la plantilla global: miniblog/apps/frontend/templates/layout.php y cambiamos el contenido de la etiqueta "body" a:

<div id="container" style="width:600px;margin:0 auto;border:1px solid grey;padding:10px">
  <div id="navigation" style="display:inline;float:right">
    <ul>
      <li><?php echo link_to('Lista de art&iacute;culos', 'articulo/list') ?></li>
      <li><?php echo link_to('Lista de comentarios', 'comentario/list') ?></li>
    </ul>
  </div>
  <div id="title">
    <h1><?php echo link_to('Mi primer proyecto de Symfony', '@homepage') ?></h1>
  </div>
 
  <div id="content" style="clear:right">
    <?php echo $sf_data->getRaw('sf_content') ?>
  </div>
</div>

Podemos cambiar el título de las páginas y otras etiquetas meta, modificando el archivo de configuración de la vista de la aplicación: miniblog/apps/frontend/config/view.yml:

default:
  http_metas:
    content-type: text/html

metas:
  title:           El mejor blog de todos
  robots:        index, follow
  description:  symfony proyecto
  keywords:    symfony, proyecto
  language:     es

Ahora vamos a cambiar el punto de acceso a la aplicación por que ahora nos muestra la página por defecto de Symfony. Vamos a crear un modulo principal:

symfony init-module frontend principal

Modificamos el archivo miniblog/apps/frontend/modules/principal/actions/actions.class.php, eliminando el contenido del método executeIndex() de la siguiente manera:

public function executeIndex()
  {
  }

Modificamos el archivo miniblog/apps/frontend/modules/principal/templates/indexSuccess.php, para agregar un mensaje de bienvenida mas lindo:

<h1> Bienvenido a mi fant&aacute;stico blog</h1>
<p>Sos el visitante n&uacute;mero <?php echo rand(1000,5000) ?> el d&iacute;a de hoy. </p>

Ahora le vamos a decir a Symfony que acción tiene que ejecutar cuando llamamos a la pagina inicial: editamos el archivo miniblog/apps/frontend/config/routing.yml y cambiamos la regla homepage:

homepage:
  url:    /
  param:  { module:principal, action: index }

Ahora chequeamos el resultado llamando a la pagina principal con la siguiente URL:
http://localhost/miniblog/web/frontend_dev.php

Se puede encontrar más información sobre plantillas en el manual.

Pasar datos desde la acción a la plantilla

Ahora vamos a juntar cada artículo con sus comentarios en una misma vista. Modificamos el archivo miniblog/apps/frontend/modules/articulo/actions/actions.class.php y cambiamos el método executeShow() agregando las últimas 4 líneas.

public function executeShow()
{
  $this->articulo = ArticuloPeer::retrieveByPk($this->getRequestParameter('id'));
  $this->forward404Unless($this->articulo);
 
  $c = new Criteria();
  $c->add(ComentarioPeer::ARTICULO_ID, $this->getRequestParameter('id'));
  $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  $this->comentarios = ComentarioPeer::doSelect($c);
}

Los objetos Criteria y -Peer son parte del mapeo de relación de objetos de Propel. Esas 4 líneas resuelven el sql para obtener los registro de la tabla de comentarios relacionados con cada artículo (el que se pase por el parametro id de la URL). La linea $this->comentarios habilita el acceso a la variable comentarios en la plantilla.
Para continuar modificamos la plantilla que muestra los artículos: miniblog/apps/frontend/modules/articulo/templates/showSuccess.php y agregamos al final el siguiente código:

...
<?php use_helper('Text', 'Date') ?>
 <hr />
<?php if ($comentarios) : ?>
  <p><?php echo count($comentarios) ?> comentario<?php if (count($comments)> 1) : ?>s
                          <?php endif; ?> en este art&iacute;culo.</p>
  <?php foreach ($comentarios as $comentario): ?>
    <p><em>Publicado por <?php echo $comentario->getAutor() ?> en
                       <?php echo format_date($comentario->getCreatedAt()) ?></em></p>
    <div class="comentario" style="margin-bottom:10px;">
      <?php echo simple_format_text($comentario->getContenido()) ?>
    </div>
  <?php endforeach; ?>
<?php endif; ?>

Esta página usa las funciones format_date y simple_format_text()) de Symfony, que se llaman 'helpers' que hacnr algunas tareas que de otra manera requerirían más tiempo y código.
Creamos un comentario para el primer artículo y despues lo probamos, haciendo click en el número de artículo de la lista o bien tipendo la siguiente URL:
http://localhost/miniblog/web/frontend_dev.php/articulo/show?id=1

Agregar un registro vinculado de otra tabla

Cuando agregas un comentario podes elegir el id del artículo relacionado. Esto no es muy amigable, vamos a cambiarlo y nos vamos a asegurar que el usuario vea el artículo que estaba comentando.
Al final del archivo miniblog/apps/frontend/modules/articulo/templates/showSuccess.php

<?php echo link_to('Comentar', 'comentario/create?articulo_id='.$articulo->getId()) ?>

El helper link_to() crea un hipervínculo que apunta a la acción del módulo comentario, para poder agregar un comentario directamente desde la página del artículo.
En el archivo miniblog/apps/frontend/modules/comentario/templates/editSuccess.php, reemplazamos las siguientes líneas:

<tr>
  <th>Art&iacute;culo:</th>
  <td><?php echo object_select_tag($comentario, 'getArticuloId', array (
  'related_class' => 'Articulo',
  'include_blank' => true,
)) ?></td>
</tr>

Por:

<?php if ($sf_params->has('articulo_id')): ?>
  <?php echo input_hidden_tag('articulo_id',$sf_params->get('articulo_id')) ?>
<?php else: ?>
  <tr>
    <th>Art&iacute;culo*:</th>
    <td><?php echo object_select_tag($comentario, 'getArticuloId',
                               array('related_class' => 'Articulo')) ?></td>
  </tr>
<?php endif; ?>

El formulario de la pagina comentario/create apunta a la acción comentario/update, que a su vez redirecciona a comentario/show cuando se acepta el formulario. Esto implica que despues de agregar un comentario nos muestre el detalle de ese comentario, cuando seria mejor que nos mostrara el artículo, con sus comentarios incluido el nuestro. Entonces, editamos miniblog/apps/frontend/modules/comentario/actions/actions.class.php y vamos al método executeUpdate(). Ahí podemos ver que el campo created_at está definido en la accion; es por que Symfony sabe que todo campo llamado created_at se carga con el tiempo (timestamp) del sistema cuando el registro es creado. Hay que cambiar la última redirección de la acción para que apunte a la correcta. Cambiarla por:

public function executeUpdate ()
{
    if (!$this->getRequestParameter('id'))
    {
      $comentario = new Comentario();
    }
    else
    {
      $comentario = ComentarioPeer::retrieveByPk($this->getRequestParameter('id'));
      $this->forward404Unless($comentario);
    }

    $comentario->setId($this->getRequestParameter('id'));
    $comentario->setArticuloId($this->getRequestParameter('articulo_id') ?
                        $this->getRequestParameter('articulo_id') : null);
    $comentario->setAutor($this->getRequestParameter('autor'));
    $comentario->setEmail($this->getRequestParameter('email'));
    $comentario->setContenido($this->getRequestParameter('contenido'));

    $comentario->save();

    return $this->redirect('articulo/show?id='.$comentario->getArticuloId());
}

Ahora los usuarios pueden agregar comentarios a un artículo y volver al mismo despues.
Querías un blog? ahí tenes un blog.
Encuentra más sobre acciones en el manual

Validación de Formularios

Para evitar que se carguen comentarios vacios o con errores vamos a armar la validación del formulario, creando el directorio y el archivo miniblog/apps/frontend/modules/comentario/validate/update.yml, y vamos a escribir lo siguiente:

methods:
  post:           [autor, email, contenido]
  get:            [autor, email, contenido]

fillin:
  enabled:       on

names:
  autor:
    required:     Yes
    required_msg: El campo autor no se puede dejar en blanco

  email:
    required:     No
    validators:   emailValidator

  contenido:
    required:     Yes
    required_msg: El campo contenido no se puede dejar en blanco

emailValidator:
  class:          sfEmailValidator
  param:
    email_error:  El email no es válido

La activación de la opción fillin habilita la recarga del formulario con los datos que cargo el usuario en caso de error. La opción names establece las reglas de validación para cada campo del formulario.
Por defecto el controlador redirecciona al usuario a la plantilla updateError.php si detecta un error, lo ideal seria que vuelva a mostrar el formulario con un mensaje que indique el error. Para esto tenemos que agregar un método handleErrorUpdate a la clase action del archivo miniblog/apps/frontend/modules/comentario/actions/actions.class.php:

public function handleErrorUpdate()
{
  $this->forward('comentario', 'create');
}

Para terminar,abrimos la plantilla miniblog/apps/frontend/modules/comentario/templates/editSuccess.php y le agregamos al inicio:

<?php if ($sf_request->hasErrors()): ?> 
  <div id="errors" style="padding:10px;">
    Por favor, corregir los siguientes errores y reenviar el formulario:
    <ul>
    <?php foreach ($sf_request->getErrors() as $error): ?>
      <li><?php echo $error ?></li>
    <?php endforeach; ?>
    </ul>
  </div>
<?php endif; ?>

Ahora probamos nuestro formulario.

Ver mas sobre validación en el manual

Cambiamos el aspecto de la URL

Podemos hacer mucho mas amigables las URLs usando el título de los artículos en vez del id. El problema es que algunos títulos pueden tenes caracteres especiales, espacios, si los dejamos la url va a mostrar algunas cosas feas como %20, es mejor extender el modelo para agregar un método al artículo que nos devuelva un título limpio. Editamos el archivo miniblog/lib/model/articulo.php y le agregamos el siguiente método:

public function getStrippedTitulo()
{
  $resultado = strtolower($this->getTitulo());
 
  // sacamos los caracteres raros
  $resultado = preg_replace('/\W/', ' ', $resultado);
 
  // reemplazamos los espacios con guiones
  $resultado = preg_replace('/\ +/', '-', $resultado);
 
  // sacamos las barras
  $resultado = preg_replace('/\-$/', '', $resultado);
  $resultado = preg_replace('/^\-/', '', $resultado);
 
  return $resultado;
}

Ahora vamos a creaar la acción permalink para el módulo artículo. Agregamos el siguiente método al archivo miniblog/apps/frontend/modules/articulo/actions/actions.class.php

public function executePermalink()
{
  $articulos = ArticuloPeer::doSelect(new Criteria());
  $titulo = $this->getRequestParameter('titulo');
  foreach ($articulos as $articulo)
  {
    if ($articulo->getStrippedTitulo() == $titulo)
    {
      break;
    }
  }
  $this->forward404Unless($articulo);
 
  $this->getRequest()->setParameter('id', $articulo->getId());
 
  $this->forward('articulo', 'show');
}

La lista de artículos puede llamar a este permalink en vez de show para cada artículo. En el archivo miniblog/apps/frontend/modules/articulo/templates/listSuccess.php borramos de la tabla la cabecera y la celda "id" y cambiamos la celda "titulo" de:

<td><?php echo $articulo->getTitulo() ?></td>

Por:

<td><?php echo link_to($articulo->getTitulo(),
         'articulo/permalink?titulo='.$articulo->getStrippedTitulo()) ?></td>

Solo un paso más: Abrimos el archivo miniblog/apps/frontend/config/routing.yml y agregamos estas reglas al principio:

lista_de_articulos:
  url:   /ultimos_articulos
  param: { module: articulo, action: list }

articulo:
  url:   /weblog/:titulo
  param: { module: articulo, action: permalink }

Ahora podemos navegar en nuestra aplicación para probarlo.

Encontra mas sobre URL amigables en el manual

Generar la aplicación administrativa

En este blog todo el mundo puede entrar y hacer un artículo y esta no es precisamente la idea. Vamos a limpiar un poco las plantillas. En la plantilla miniblog/apps/frontend/modules/articulo/templates/showSuccess.php y borramos la siguiente línea:

<?php echo link_to('edit', 'articulo/edit?id='.$articulo->getId()) ?>

Y hacemos lo mismo en miniblog/apps/frontend/modules/articulo/templates/listSuccess.php y borramos la línea:

<?php echo link_to ('create', 'articulo/create') ?>

Tambien tenes que eliminar los siguientes métodos del archivo miniblog/apps/frontend/modules/articulo/actions/actions.class.php:

executeCreate()
executeEdit()
executeUpdate()
executeDelete()

Bien, ahora nadie puede publicar un artículo.

Generar el Backend

Vamos a crear el backend tipeando en consola los siguientes comandos:

symfony init-app backend
symfony propel-init-admin backend articulo Articulo
symfony propel-init-admin backend comentario Comentario

Esta vez usamos el generador admin, que ofrece muchas mas opciones de configuración que el generador CRUD básico:
Tal como hicieramos en el frontend, editamos el Layout (miniblog/apps/backend/templates/layout.php) para agregar la navegacion global:

<div id="navigation">
  <ul style="list-style:none;">
    <li><?php echo link_to('Administrar art&iacute;culos', 'articulo/list') ?></li>
    <li><?php echo link_to('Administrar comentarios', 'comentario/list') ?></li>
  </ul>
</div>
<div id="content">
  <?php echo $sf_data->getRaw('sf_content') ?>
</div>

y accedemos con la siguiente URL:
http://localhost/miniblog/web/backend_dev.php/articulo

La gran ventaja de esta administración generada es que podemos configurarla con solo editar el archivo de configuración: miniblog/apps/backend/modules/post/config/generator.yml, cambiamos su contenido por lo siguiente:

generator:
  class:              sfPropelAdminGenerator
  param:
    model_class:      Articulo
    theme:            default
    fields:
      titulo:          { name: Titulo }
      resumen:         { name: Resumen }
      contenido:       { name: Contenido }
      nro_comentarios: { name: Comentarios }
      created_at:      { name: Fecha de Creacion }
    list:
      title:          Lista de Articulos
      layout:         tabular
      display:        [=titulo, resumen, nro_comentarios, created_at]
      object_actions:
        _edit:        ~
        _delete:      ~
      max_per_page:   5
      filters:        [titulo, created_at]
    edit:
      title:          Detalle de Articulo
      fields:
        titulo:           { type: input_tag, params: size=53 }
        resumen:       { type: textarea_tag, params: size=50x2 }
        contenido:     { type: textarea_tag, params: size=50x10 }
        created_at:   { type: input_date_tag, params: rich=on }

Se puede ver que el campo nro_comentarios no está establecido, por eso vamos a crear un getter agregando al archivo miniblog/lib/model/articulo.php, lo siguiente:

public function getNroComentarios()
{
  return count($this->getComentarios());
}

Ahora actualizamos la página de administración y vemos los cambios:

Restringir el acceso al backend

Hasta ahora cualquiera puede entrar al backend, vamos a agregar restricciones. Agregamos el archivo miniblog/apps/backend/modules/articulo/config/security.yml con el contenido:

all:
  is_secure: on

y lo copiamos en miniblog/apps/backend/modules/comentario/config/
Ahora no podemos entrar al backend, a no ser que estemos logueados, pero no existe el login, solo nos muestra la pagina por defecto de symfony. Para agregarlo creamos el módulo de seguridad:
symfony init-module backend seguridad
Este nuevo módulo lo vamos a usar para manejar el login y la petición. Editamos el archivo miniblog/apps/backend/modules/seguridad/templates/indexSuccess.php para crear el formulario de login:

<h2>Authenticaci&oacute;n</h2>
 
<?php if ($sf_request->hasErrors()): ?>
  Fall&oacute; la identificaci&oacute;n - Por favor trate de nuevo
<?php endif; ?>
 
<?php echo form_tag('seguridad/login') ?>
  <label for="login">Usuario:</label>
  <?php echo input_tag('login', $sf_params->get('login')) ?>
 
  <label for="password">Contraseña:</label>
  <?php echo input_password_tag('password') ?>
 
  <?php echo submit_tag('submit', 'class=default') ?>
</form>

Agregamos la acción login que será llamada por el formulario del módulo seguridad en el archivo miniblog/apps/backend/modules/seguridad/actions/actions.class.php

public function executeLogin()
{
  if ($this->getRequestParameter('login') == 'admin'
                    && $this->getRequestParameter('password') == 'password')
  {
    $this->getUser()->setAuthenticated(true);
 
    return $this->redirect('/articulo');
  }
  else
  {
    $this->getRequest()->setError('login', 'incorrect entry');
 
    return $this->forward('seguridad', 'index');
  }
}

y borramos el contenido por defecto de la acción index

public function executeIndex()
  {
  }

Lo último que tenemos que hacer es establecer el módulo de seguridad como modulo por defecto para manejar las acciones de login. Abrimos el archivo miniblog/apps/backend/config/settings.yml y agregamos:

all:
  .actions:
    login_module:          seguridad
    login_action:           index

Ahora cuando intentemos ingresar al backend nos va a pedir el usuario (admin) y la contraseña (password).

Mas sobre seguridad en el manual

Conclusión

Ok, se termino la hora. Lo hiciste. Ahora podes probar ambas aplicaciones en el entorno de producción:

frontend: http://localhost/miniblog/web/index.php/
backend: http://localhost/miniblog/web/backend.php/

Si te surge algun error es por que algunas cambio el modelo luego de haber generado el cache, que no esta activado el el entorno de desrrollo. Para limpiar el cache solo tenes que tipear en consola:
symfony cc
Vas a ver que la aplicación funciona rápido y sin problemas.

12 Comments »

  1. pe_la_do dice,

    February 11, 2008 at 10:27

    Muy bueno el tuto. Yo recién estoy comenzando y la verdad que el framework esta muy bueno.

  2. antonio khalifa dice,

    March 14, 2008 at 19:40

    execelente buen trabajo sigue asi!!

  3. Eduardo dice,

    March 27, 2008 at 12:29

    Hola:
    Recien estoy haciendo mis primeros pasos con Symfony y este tutorial me parecio muy esclarecedor
    Encontre un pequeño error (al menos lo solucione como detallo mas abajo) en el codigo que se coloca en la plantilla de articulos, decia:

    comentario 1) : ?>s
    en este artículo.

    y en realidad debe ser:

    comentario 1) : ?>s
    en este artículo.

    Ademas queria consultar de que forma se puede agregar un Filtro (como los filters de los generadores) para filtrar alguna lista generada con CRUD ya que no es tan automatico como con los generadores generate.yml
    Seria uno tema interesante tu opinion

    Desde ya muy agradecido

  4. paco dice,

    April 9, 2008 at 18:38

    Muy buena la interpretacion del manual. Muchas gracias por el aporte a la comunidad hispano-parlante.
    Traduciras mas cosas? seguiras ampliando la seccion de symfony?

    SAludos

  5. RetroFOX dice,

    April 10, 2008 at 10:54

    Tenemos que organizarnos un poco mejor, pero si, la idea es encarar symfony con mas intensidad.
    Saludos.

  6. Juan dice,

    April 16, 2008 at 7:50

    EEEEEEEE coolegas como se pueden cojer datos de una tabla distinta desde generator.yml.

    Me explico yo stoy utilizando una tabla k me referencia a otra a traves del id, pero lo que me gustartia es mostrar otro campo, por ejemplo el nombre

  7. Pinien dice,

    April 16, 2008 at 11:06

    Juan, para eso lo que te conviene usar es el método mágico PHP __toString(). Debes crearlo en la clase dentro del modelo de la tabla original. Por ejemplo si queres mostrar el titulo del articulo en lugar del id debes editar el archivo lib/model/Articulo.php, de la siguiente manera:

    class Articulo extends BaseArticulo
    {
    public function __toString()
    {
    return self::getTitulo();
    }
    }
    De esa manera cuando va a mostrar el titulo en lugar del id.
    El uso de estos métodos es buenisimo.
    Espero te sirva

  8. Juan dice,

    April 18, 2008 at 7:19

    Muchas gracias Pinien,
    pero ahora tengo otra duda. . . . . .

    ¿ Como puedo hacer un type radio con dos opciones en un generator.yml ?
    Es que el tema es que se hacerlo pero se me marcan las 2 opciones yo lo he hecho asi:

    nfactura:
    name: Factura
    params: { type: radio }
    npresupuesto: { params: type: radio }

  9. RetroFOX dice,

    June 11, 2008 at 17:10

    Creo que está mal definida una variable cuando queremos Pasar datos desde la acción a la plantilla. Al contar la cantidad de elementos del array con count hace referencia a la variable $comments que no está definida, esta debería ser $comentarios. :-D
    Saludos.

  10. horacio dice,

    June 18, 2008 at 19:57

    hola, muy bueno el mini tutorial de symfony, muy entendible
    Me fue todo perfecto hasta la parte de validacion de formularios no tengo el archivo miniblog/apps/frontend/modules/comentario/validate/update.yml, mi directorio llega hasta comentario, no tengo el directorio validate, debo configurar algo para que me aparezca eso?????????? gracias

  11. horacio dice,

    June 19, 2008 at 9:57

    hola, yo de nuevo, mi problema en realidad fue que no lei bien jajaja, disculpen por haber posteado esto, muy bueno todo.

  12. Pinien dice,

    June 19, 2008 at 10:01

    Oki, no hay problema! saludos

Comentarios