Das Generieren von Formularen mit Symfony 2.8 löst einen Twig_Error_Runtime aus

Lesezeit: 5 Minuten

Benutzer-Avatar
cezar

Seit die letzte LTS-Version von Symfony vor wenigen Tagen (30.11.2015) veröffentlicht wurde, habe ich angefangen, damit zu spielen. Leider kann ich keine CRUD mit Schreibaktionen mit demselben Code generieren, der in Symfony 2.7.7 einwandfrei funktioniert.

Zuerst erstelle ich ein neues Symfony-Projekt mit der bash unter Linux Mint 17.2:

symfony new tasks lts

Das neue Verzeichnis tasks wird mit einem neuen Symfony 2.8.0-Projekt erstellt.

Nach dem Anpassen der Datenbankanmeldeinformationen in app/config/parameters.yml Ich erstelle die Datenbank:

app/console doctrine:database:create

und generiere ein neues Bundle:

app/console generate:bundle --namespace=Acme/TasksBundle --format=yml

Dann erstelle ich ein neues Verzeichnis src/Acme/TasksBundle/Resources/config/doctrine und lege zwei Dateien für meine Modelle hinein. Diese sind:

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

Das Datenbankschema sollte wie folgt aussehen:

+----------------+     +--------------+
| task           |     | task_tag     |     +---------+
+----------------+     +--------------+     | tag     |
|   id           |<--->|   task_id    |     +---------+
|   description  |     |   tag_id     |<--->|   id    |
+----------------+     +--------------+     |   name  |
                                            +---------+

Jetzt kann ich die Entitäten generieren:

app/console generate:doctrine:entities AcmeTasksBundle

Dies funktioniert gut, sodass die Datenbank aktualisiert werden kann:

app/console doctrine:schema:update --force

Alles ok bis jetzt. Die Tabellen befinden sich in der Datenbank. Jetzt möchte ich CRUD mit Schreibaktionen generieren:

app/console generate:doctrine:crud --entity=AcmeTasksBundle:Task --with-write --format=yml

Nach Bestätigung einiger Fragen generiert es das CRUD und druckt Folgendes aus:

Generating the CRUD code: OK

und wirft danach diesen Fehler:

[Twig_Error_Runtime]                                                                                    
Key "tags" for array with keys "id, description" does not exist in "form/FormType.php.twig" at line 29

Der Controller wird erstellt, aber nicht das Formular.

Das Generieren des CRUD ohne Schreiboptionen funktioniert einwandfrei. Derselbe Code funktioniert einwandfrei mit Symfony 2.7.7.

Ich habe die Unterschiede in der Datei überprüft form/FormType.php.twig zwischen den Versionen und hier sind die relevanten Teile:

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 %}

Wie ich sehe, ist die if-Bedingung in der for-Schleife der Ort, an dem der Fehler auftritt. (Ich nehme an, dass der Ausdruck fields_mapping[field]['type'] verursacht das Problem, da das Many-to-Many-Feld (tag) hat kein Attribut type.)

Was mache ich falsch? Wie kann ich dieses Problem lösen? Vielen Dank für Ihre Hilfe.

EDIT: Das gleiche Problem tritt bei Symfony 3.0.0 auf. Die Datei form/FormType.php.twig wurde seit Version 2.8 geändert.

Sieht aus wie eine Regression danach Datumszeit beheben im Generatorbündel.

Eine schnelle Lösung ist die Rückkehr zu v2.* in Ihrem composer.json:

"sensio/generator-bundle": "^2.5",

Die beste Lösung besteht darin, das Repo zu forken, den Fehler zu beheben und eine Pull-Anforderung zu erstellen, um einen Beitrag zur Community zu leisten.

Da Sie bereits alles getan haben, um den Fehler zu isolieren, ist die Lösung trivial: Überprüfen Sie, ob type existiert in Resources/skeleton/form/FormType.php.twig. Etwas wie

{%- if fields_mapping[field]['type'] is defined and fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

es sei denn, der Fehler maskiert weitere versteckte Fehler, die auf derselben Annahme basieren.

  • Vielen Dank! Ich schreibe nur eine lange Antwort mit meinen Forschungsergebnissen. Meine Lösung ist nur etwas anders, aber die Idee ist die gleiche.

    – Cézar

    7. Dezember 2015 um 10:19 Uhr

Benutzer-Avatar
cezar

Ich habe ein wenig recherchiert und versucht, den Fehler zu debuggen.

Wie ich oben erwähnt habe, die Datei form/FormType.php.twig wurde seit der Version 2.8.0 geändert.

Offensichtlich wollten die Symfony-Macher die Formulare verbessern und die Typen automatisch auflösen date, time und datetime. Dies geschieht in der Zeile:

{%- if fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

Dies soll mit Hilfe des Arrays erreicht werden fields_mapping.

Mit einigen Quick-and-Dirty-Workarounds habe ich versucht herauszufinden, was sich darin verbirgt fields_mapping. Das ist das Ergebnis für mein Modell:

Aufgabe

{
    id => {
        id => 1,
        fieldName => id,
        type => integer,
        columnName => id
    },
    description => {
        fieldName => description,
        type => text,
        columnName => description
    }
}

Beim Durchlaufen der Task-Felder wird im letzten Schritt das Feld durchlaufen tags. Der Ausdruck in der if-Klausel sieht so aus:

fields_mapping['tags']['type']

Wie wir im vorherigen Beispiel sehen, gibt es keinen Schlüssel tags in dem fields_mapping nur für Aufgabe id und description. Da der Schlüssel tags existiert nicht, wird der Fehler ausgegeben.

Ich habe die betreffende Zeile in der Datei geändert form/FormType.php.twig so aussehen:

{%- if fields_mapping[field] is defined and fields_mapping[field]['type'] in ['date', 'time', 'datetime'] %}

Jetzt können wir die neue Funktion nutzen und einen Fehler verhindern, indem wir prüfen, ob der Schlüssel im Array vorhanden ist.

Ich weiß nicht, ob dies ein Fehler ist oder in meinem speziellen Fall etwas nicht stimmt. Nun ist es schon eine Woche her seit der Veröffentlichung der Versionen 2.8.0 und 3.0.0, also haben wohl schon viele tausend User damit rumgespielt. Ich konnte nicht glauben, dass, wenn es ein Fehler ist, niemand das bemerkt hätte.

BEARBEITEN:

Ich habe ein Problem auf GitHub gepostet:

https://github.com/sensiolabs/SensioGeneratorBundle/issues/443

Dies war ein Fehler, der auf die gleiche Weise behoben wurde, wie ich oben dachte und schrieb:

https://github.com/Maff-/SensioGeneratorBundle/commit/205f64e96a94759f795271cb00fc86fb03b1fd4a

Benutzer-Avatar
Cortez

Auch wenn das Problem nach der Aktualisierung des festen Pakets immer noch besteht, ist es manchmal am einfachsten, das Problem zu löschen vendor Katalog und Komponist aktualisieren.

1057400cookie-checkDas Generieren von Formularen mit Symfony 2.8 löst einen Twig_Error_Runtime aus

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy