Crear formularios con relaciones m:n en Symfony 1.4

El cambio de Symfony 1.0 al Symfony 1.4 no fue tan complicado como pensé que sería. Pero supongo que tanto a mi como a otros cuantos, les habrá ocurrido que enfrentarse a entender la construcción de formularios no es fácil. Aunque una vez superado esto, entiendes lo que significa. A pesar de sus bondandes y, en general, las bondades del symfony, no me parece que los formularios sigan del todo un patron MVCW (mi humilde opinión).

Volviendo al tema, una de las cosas que me fue dificil de crear fue un simple formulario que guardara datos en tablas estructuradas con relacion muchos a muchos. Y por la poca documentación que encontré, pongo a disposición un ejemplo que espero le sirva a alguien.

Para el ejemplo vamos a suponer que tenemos un blog. De ese blog cada entrada (article) tiene varias categorias (category) y varias etiquetas (tags). Para que lo obviamente necesitaremos relaciones muchos a muchos (muchas entradas pueden tener muchas categorias, y muchas entradas pueden muchas etiquetas). El schema.yml sería algo como esto:

propel:
article:
id: ~
title: { type: varchar(255), required: true }
slug: { type: varchar(255), required: true }
content: longvarchar
status: varchar(255)
author_id: { type: integer, required: true, foreignTable: author, foreignReference: id, OnDelete: cascade }
category_id: { type: integer, required: false, foreignTable: category, foreignReference: id, onDelete: setnull }
published_at: timestamp
created_at: ~
updated_at: ~
_uniques:
unique_slug: [slug]

author:
id: ~
first_name: varchar(20)
last_name: varchar(20)
email: { type: varchar(255), required: true }
active: boolean

category:
id: ~
name: { type: varchar(255), required: true }

tag:
id: ~
name: { type: varchar(255), required: true }

article_tag:
article_id: { type: integer, foreignTable: article, foreignReference: id, primaryKey: true, onDelete: cascade }
tag_id: { type: integer, foreignTable: tag, foreignReference: id, primaryKey: true, onDelete: cascade }

Uno de los errores frecuentes ocurre por una mala definición de las tablas. Se debe tener en cuenta que las tablas que manejan la relacion m:n debe tener sus dos campos establecidos como una llave primaria para esa tabla, y establecer las llaves foráneas correctamente.

# Creamos el modelo:
./symfony propel:build-model

# Luego creamos los formularios:
./symfony propel:build-forms

# Limpiamos la caché:
./symfony cc

# Se crea el modulo que utiliza el formulario:
./symfony propel:generate-module app nombreModulo nombreClase

Cuando accedemos al formulario veremos que nos mostrará la lista de categorias disponibles y la lista de etiquetas disponibles.

Y ¿si quiero agregar el campo manualmente a un formulario que ya existe?

Pues bien, luego de haber definido correctamente tus tablas, debes re-hacer el model, re-hacer los formularios:

./symfony propel:build-model
./symfony propel:build-forms
./symfony cc

Vas al fomulario, y agregar el campo. Suponiendo que en la tabla m:n (post_category) existen los campos id_post y id_category, donde ambos conforman una clave primaria y ambos son claves foráneas con sus respectivas tablas (post y category). Vamos al formulario principal (que deberís ser post) y agregamos nuestro campo:

$form['post_category_list']->render();

Y listo, tenemos nuestro nuevo campo.

Demás esta decir que symfony se encarga del resto, es decir, de hacer efectivas las relaciones, guarda los datos en sus respectivas tablas. Actualiza, elimina, crea, sin necesidad de alguna configuraciòn extra. No se requiere embeber formularios.

Enlaces de interés:


Comentarios

  1. daridos dice:

    Hola
    buen tuto

    tengo una consulta

    $form[‘post_category_list’]->render();

    se agrega en la vista

  2. Yenny dice:

    Hola,

    no se si puedas ayudarme, pero tengo una relación m:n y las clases(tablas) son las siguientes:

    Trabajador: {id, nombre, cedula…etc}
    Trabajador_Cargo: {trabjador_id, cargo_id, fecha}
    Cargo: {id, descripcion}

    Tengo mi schema donde está especificada la relacion m:n donde Trabajador_cargo tiene como clave las claves de las otras dos tablas, y lo que deseo es mostrar en el formulario de trabajador el cargo que ocupa dicho trabajador y la fecha.
    Ya tengo hecha la consulta con el inner join en en TrabajadorTable.class

    Agradeceria tu ayuda.


Deja un comentario

*
*
*
Loading... Enviando...