El gestor de artículos permite modificar la información de las tablas article
, author
, category
y tag
. Para ello, es preciso crear formularios asociados a cada tabla y configurar los widgets y validadores necesarios para cumplir las restricciones del esquema de la base de datos. Aunque los formularios se pueden crear a mano, se trata de una tarea repetitiva y tediosa que requiere repetir la misma información una y otra vez en diferentes archivos (el nombre de las columnas y los campos, el tamaño máximo de las columnas y campos, etc.) Además, cada vez que se modifica el modelo, es necesario modificar la clase del formulario asociado. Afortunadamente, el plugin de Doctrine incluye una tarea llamada doctrine:build-forms
que automatiza todo este proceso y genera los formularios relacionados con el modelo de objetos:
$ ./symfony doctrine:build-forms frontend
La tarea de generación automática de formularios crea una clase para cada tabla y añade los validadores y widgets necesarios para cada columna mediante la introspección del modelo y teniendo en cuenta las relaciones entre tablas.
Nota Las tareas doctrine:build-all
y doctrine:build-all-load
también actualizan las clases de los formularios porque invocan automáticamente la tarea doctrine:build-forms
.
Después de ejecutar estas tareas se crea una estructura de archivos en el directorio lib/form/
. El siguiente listado muestra los archivos creados para el esquema utilizado en los ejemplos anteriores:
lib/ form/ doctrine/ BaseFormDoctrine.class.php ArticleForm.class.php ArticleTagForm.class.php AuthorForm.class.php CategoryForm.class.php TagForm.class.php base/ BaseArticleForm.class.php BaseArticleTagForm.class.php BaseAuthorForm.class.php BaseCategoryForm.class.php BaseFormDoctrine.class.php BaseTagForm.class.php
La tarea doctrine:build-forms
genera dos clases para cada tabla del esquema, una clase base en el directorio lib/form/base
y otra clase en el directorio lib/form/
. Si se considera por ejemplo la tabla author
, se crean las clases BaseAuthorForm
y AuthorForm
que se guardan en los archivos lib/form/base/BaseAuthorForm.class.php
y lib/form/AuthorForm.class.php
.
La siguiente tabla muestra la jerarquía de las diferentes clases relacionadas con el formulario AuthorForm
.
Clase | Paquete package | Quién utiliza la clase | Descripción |
---|---|---|---|
AuthorForm |
project |
Programador | Redefine el formulario generado |
BaseAuthorForm |
project |
Symfony | Se basa en el esquema y se genera cada vez que se ejecuta la tarea doctrine:build-forms |
BaseFormDoctrine |
project |
Programador | Permite personalizar los formularios de Doctrine de forma global |
sfFormDoctrine |
Plugin Doctrine | Symfony | Base de los formularios de Doctrine |
sfForm |
symfony |
Symfony | Base de los formularios de Symfony |
El listado 11-2 muestra el código de la clase AuthorForm
, utilizada para crear y modificar los objetos de la clase Author
. Como se puede observar, esta clase no contiene ningún método, ya que hereda de la clase BaseAuthorForm
que se genera a partir de la configuración. La clase AuthorForm
se utiliza para personalizar y redefinir la configuración del formulario.
Listado 11-2 - La clase AuthorForm
class AuthorForm extends BaseAuthorForm
{
public function configure()
{
}
}
El listado 11-3 muestra el código de la clase BaseAuthorForm
con los validadores y widgets generados automáticamente mediante la instrospección del modelo de la tabla author
.
Listado 11-3 - Clase BaseAuthorForm
que representa al formulario de la tabla author
class BaseAuthorForm extends BaseFormDoctrine
{
public function setup()
{
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
'first_name' => new sfWidgetFormInput(),
'last_name' => new sfWidgetFormInput(),
'email' => new sfWidgetFormInput(),
));
$this->setValidators(array(
'id' => new sfValidatorDoctrineChoice(array('model' => 'Author', 'column' => 'id', 'required' => false)),
'first_name' => new sfValidatorString(array('max_length' => 20, 'required' => false)),
'last_name' => new sfValidatorString(array('max_length' => 20, 'required' => false)),
'email' => new sfValidatorString(array('max_length' => 255)),
));
$this->widgetSchema->setNameFormat('author[%s]');
$this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
parent::setup();
}
public function getModelName()
{
return 'Author';
}
}
La clase generada es muy similar a la de los formularios creados en los capítulos anteriores, salvo por las siguientes excepciones:
- La clase base es
BaseFormDoctrine
en vez desfForm
- La configuración de los validadores y widgets se realiza en el método
setup()
, en vez de en el métodoconfigure()
- El método
getModelName()
devuelve la clase de Doctrine relacionada con el formulario
Nota Las clases base utilizan el método setup()
para su configuración en vez del método configure()
. De esta forma es posible redefinir la configuración de las clases vacías generadas automáticamente sin utilizar una llamada a parent::configure()
.
Los nombres de los campos del formulario son idénticos a los nombres de las columnas del esquema de datos: id
, first_name
, last_name
y email
.
La tarea doctrine:build-forms
genera un widget y un validador para cada columna de la tabla author
cumpliendo las restricciones del esquema de datos. Esta tarea siempre genera los validadores más seguros posible. Si se considera el campo id
, se podría comprobar simplemente si es un número entero válido. Sin embargo, el validador generado también comprueba que ese identificador exista en la base de datos (para modificar un objeto existente) o sea vacío (para poder crear un nuevo objeto). La validación generada automáticamente es mucho más segura que comprobar simplemente que sea un número entero.
La mayor ventaja de los formularios generados es que se pueden utilizar inmediatamente. Si se añade la instrucción <?php echo $form ?>
en la página, ya se dispone de un formulario completamente funcional sin haber escrito ni una sola línea de código.
Además de la posibilidad de crear prototipos rápidamente, los formularios generados se pueden modificar sin necesidad de cambiar las clases generadas automáticamente, gracias a la herencia entre las clases base y las clases de los formularios.
Por último, cada vez que se modifica el esquema de la base de datos, esta tarea genera de nuevo todos los formularios para tener en cuenta las modificaciones manteniendo las modificaciones realizadas en las otras clases.