php - La generación de formularios con Symfony 2.8 arroja Twig_Error_Runtime
doctrine symfony-2.8 (3)
Desde que se lanzó la última versión LTS de Symfony hace unos días (30.11.2015) comencé a jugar con ella. Desafortunadamente no puedo generar un CRUD con acciones de escritura con el mismo código que funciona bien en Symfony 2.7.7.
Primero creo un nuevo proyecto de Symfony usando bash
en Linux Mint 17.2:
symfony new tasks lts
Las nuevas tasks
directorio se crean con un nuevo proyecto Symfony 2.8.0 dentro.
Después de adaptar las credenciales de la base de datos en app/config/parameters.yml
creo la base de datos:
app/console doctrine:database:create
y generar un nuevo paquete:
app/console generate:bundle --namespace=Acme/TasksBundle --format=yml
Luego creo un nuevo directorio src/Acme/TasksBundle/Resources/config/doctrine
y src/Acme/TasksBundle/Resources/config/doctrine
dos archivos para mis modelos dentro. Estos son:
Task.orm.yml
Acme/TasksBundle/Entity/Task:
type: entity
repositoryClass: Acme/TasksBundle/Repository/TaskRepository
table: task
id:
id:
type: integer
generator: { strategy : AUTO }
fields:
description:
type: text
manyToMany:
tags:
targetEntity: Tag
inversedBy: tasks
cascade: [ "persist" ]
joinTable:
name: task_tag
joinColumns:
task_id:
referencedColumnName: id
inverseJoinColumns:
tag_id:
referencedColumnName: id
Tag.orm.yml
Acme/TasksBundle/Entity/Tag:
type: entity
repositoryClass: Acme/TasksBundle/Repository/TagRepository
table: tag
id:
id:
type: integer
generator: { strategy : AUTO }
fields:
name:
type: string
length: 50
manyToMany:
tasks:
targetEntity: Task
mappedBy: tags
El esquema de la base de datos debería tener esto:
+----------------+ +--------------+
| task | | task_tag | +---------+
+----------------+ +--------------+ | tag |
| id |<--->| task_id | +---------+
| description | | tag_id |<--->| id |
+----------------+ +--------------+ | name |
+---------+
Ahora puedo generar las entidades:
app/console generate:doctrine:entities AcmeTasksBundle
Esto funciona bien, por lo que la base de datos se puede actualizar:
app/console doctrine:schema:update --force
Todo está bien hasta ahora. Las tablas están en la base de datos. Ahora quiero generar CRUD con acciones de escritura:
app/console generate:doctrine:crud --entity=AcmeTasksBundle:Task --with-write --format=yml
Después de confirmar algunas preguntas, genera el CRUD e imprime:
Generating the CRUD code: OK
y luego arroja este error:
[Twig_Error_Runtime]
Key "tags" for array with keys "id, description" does not exist in "form/FormType.php.twig" at line 29
El controlador se crea, pero no la forma.
Generar el CRUD sin opciones de escritura funciona bien. El mismo código funciona sin problemas con Symfony 2.7.7.
form/FormType.php.twig
las diferencias en el form/FormType.php.twig
archivo form/FormType.php.twig
entre las versiones y aquí están las partes relevantes:
Symfony 2.7.7
vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/form/FormType.php.twig
{%- if fields|length > 0 %}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
{%- for field in fields %}
->add(''{{ field }}'')
{%- endfor %}
;
}
{% endif %}
Symfony 2.8.0
vendor/sensio/generator-bundle/Resources/skeleton/form/FormType.php.twig
{%- if fields|length > 0 %}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
{%- for field in fields -%}
{%- if fields_mapping[field][''type''] in [''date'', ''time'', ''datetime''] %}
->add(''{{ field }}'', ''{{ fields_mapping[field][''type''] }}'')
{%- else %}
->add(''{{ field }}'')
{%- endif -%}
{%- endfor %}
;
}
{% endif %}
Como veo la condición if en el ciclo for es el lugar donde ocurre el error. (Supongo que la expresión fields_mapping[field][''type'']
causa el problema, ya que el campo many to many ( tag
) no tiene ningún type
atributo).
¿Que estoy haciendo mal? ¿Como puedó resolver esté problema? Muchas gracias por su ayuda.
EDITAR: El mismo problema ocurre con Symfony 3.0.0. El archivo form/FormType.php.twig
ha sido cambiado desde la versión 2.8.
Estuve investigando un poco e intenté depurar el error.
Como mencioné anteriormente, el archivo form/FormType.php.twig
ha sido cambiado desde la versión 2.8.0.
Obviamente, los fabricantes de Symfony querían mejorar los formularios y resolver automáticamente los tipos de date
, time
y datetime
y datetime
. Esto sucede en la línea:
{%- if fields_mapping[field][''type''] in [''date'', ''time'', ''datetime''] %}
Esto se debe lograr con la ayuda de la matriz fields_mapping
.
Con algunas soluciones rápidas y sucias intenté descubrir qué hay escondido dentro de fields_mapping
. Este es el resultado de mi modelo:
Tarea
{
id => {
id => 1,
fieldName => id,
type => integer,
columnName => id
},
description => {
fieldName => description,
type => text,
columnName => description
}
}
Al recorrer los campos de Tarea, en el último paso pasa por las tags
campo. La expresión en la cláusula if se ve así:
fields_mapping[''tags''][''type'']
Como vemos en el ejemplo anterior, no hay tags
clave en fields_mapping
para Task, solo id
y description
. Como las tags
clave no existen, se genera el error.
Cambié la línea en cuestión en el form/FormType.php.twig
archivo form/FormType.php.twig
para que se vea así:
{%- if fields_mapping[field] is defined and fields_mapping[field][''type''] in [''date'', ''time'', ''datetime''] %}
Ahora podemos usar la nueva característica y evitamos un error comprobando si la clave existe en la matriz.
No sé si esto es un error o hay algo mal en mi caso particular. Ahora ya es una semana desde el lanzamiento de las versiones 2.8.0 y 3.0.0, por lo que probablemente miles de usuarios hayan estado jugando con ellos. No podía creer eso, si es un error, nadie se habría dado cuenta de esto.
EDITAR:
Publiqué un problema en GitHub:
https://github.com/sensiolabs/SensioGeneratorBundle/issues/443
Este fue un error, que se ha resuelto de la misma manera, como pensé y escribí arriba:
https://github.com/Maff-/SensioGeneratorBundle/commit/205f64e96a94759f795271cb00fc86fb03b1fd4a
Incluso si después de actualizar el paquete fijo, el problema sigue existiendo, a veces la forma más fácil de resolver el problema es eliminar el catálogo del vendor
y actualizar el compositor.
Parece una regresión después del arreglo de fecha y hora en el paquete del generador.
Una solución rápida es volver a v2. * En su composer.json
:
"sensio/generator-bundle": "^2.5",
La mejor solución es bifurcar el repositorio, arreglar el error y crear una solicitud de extracción para contribuir a la comunidad.
Como ya hiciste todo el trabajo para aislar el error, la solución es trivial: comprueba si existe el type
en Resources/skeleton/form/FormType.php.twig
. Algo como
{%- if fields_mapping[field][''type''] is defined and fields_mapping[field][''type''] in [''date'', ''time'', ''datetime''] %}
a menos que el error enmascare más errores ocultos basados en la misma suposición.