2015-12-03 8 views
25

Poiché l'ultima versione LTS di Symfony è stata rilasciata pochi giorni fa (30.11.2015) ho iniziato a giocarci. Sfortunatamente non riesco a generare un CRUD con azioni di scrittura con lo stesso codice che funziona bene in Symfony 2.7.7.Generazione di moduli con Symfony 2.8 genera un Twig_Error_Runtime

Per prima cosa ho creare un nuovo progetto Symfony utilizza il bash sotto Linux Mint 17.2:

symfony new tasks lts 

La nuova directory tasks viene creato con un nuovo progetto Symfony 2.8.0 dentro.

Dopo aver adattato le credenziali del database in app/config/parameters.yml ho creare il database:

app/console doctrine:database:create 

e generare un nuovo bundle:

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

Poi creo una nuova directory src/Acme/TasksBundle/Resources/config/doctrine e posizionare due file per i miei modelli dentro. Questi sono:

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 

Lo schema del database dovrebbe in questo modo:

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

ora posso generare il entità:

app/console generate:doctrine:entities AcmeTasksBundle 

Questo funziona bene, in modo che il database può essere aggiornato:

app/console doctrine:schema:update --force 

Tutto ok fino ad ora. Le tabelle sono nel database. Ora voglio generare CRUD con le azioni di scrittura:

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

Dopo aver confermato alcune domande genera il CRUD e stampa:

Generating the CRUD code: OK 

e poi getta questo errore:

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

Il il controller viene creato, ma non il modulo.

Generare il CRUD senza opzioni di scrittura funziona correttamente. Lo stesso codice funziona perfettamente con Symfony 2.7.7.

ho controllato le differenze nel file form/FormType.php.twig tra le versioni e qui ci sono le parti pertinenti:

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

A mio if condizione nel ciclo for è il luogo in cui si è verificato l'errore. (Suppongo che l'espressione fields_mapping[field]['type'] causa il problema dal momento che il campo molti a molti (tag) non ha attributi type.)

Quello che sto facendo male? Come posso risolvere questo problema? Grazie mille per il tuo aiuto.

MODIFICA: Lo stesso problema si verifica con Symfony 3.0.0. Il file form/FormType.php.twig è stato modificato dalla versione 2.8.

risposta

15

Stavo cercando un po 'e ho cercato di eseguire il debug dell'errore.

Come già detto, il file form/FormType.php.twig è stato modificato dalla versione 2.8.0.

Ovviamente i produttori di Symfony hanno voluto migliorare i moduli e risolvere automaticamente i tipi date, time e datetime. Questo accade in linea:

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

ciò può essere ottenuto con l'aiuto della matrice fields_mapping.

Con alcuni soluzioni temporanee e sporche ho cercato di scoprire cosa si nasconde all'interno di fields_mapping. Questo è il risultato per il mio modello:

Task

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

Quando l'iterazione attraverso i campi di attività, nell'ultimo passaggio passa attraverso il campo tags. L'espressione nella clausola if è simile al seguente:

fields_mapping['tags']['type'] 

Come si vede nell'esempio precedente, non c'è una chiave tags nel fields_mapping per attività, solo id e description. Poiché la chiave tags non esiste, viene generato l'errore.

ho cambiato la linea interessata nel file form/FormType.php.twig a guardare come questo:

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

Ora possiamo utilizzare la nuova funzionalità e impedire che un errore controllando se la chiave esiste nella matrice.

Non so se questo è un bug o c'è qualcosa di sbagliato nel mio caso particolare. Ora è già passata una settimana dal rilascio delle versioni 2.8.0 e 3.0.0, quindi probabilmente molte migliaia di utenti hanno giocato con loro. Non potevo credere che, se fosse un insetto, nessuno lo avrebbe notato.

EDIT:

ho postato un problema su GitHub:

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

Questo è stato un errore, che è stato risolto nello stesso modo, come ho pensato e scritto sopra:

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

17

Sembra una regressione dopo datetime fix nel gruppo generatore.

Una soluzione rapida è quella di ripristinare v2 * nel vostro composer.json:.

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

La soluzione migliore è quella di sborsare il repo, correggere il bug e creare una richiesta di pull di contribuire alla comunità.

Dato che hai già fatto tutto il lavoro per isolare il bug, la correzione è banale: controlla se type esiste in Resources/skeleton/form/FormType.php.twig. Qualcosa come

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

a meno che il bug maschera più errori nascosti basati sulla stessa ipotesi.

+0

Grazie! Sto solo scrivendo una lunga risposta con i miei risultati di ricerca. La mia soluzione è leggermente diversa, ma l'idea è la stessa. – cezar

3

Anche se dopo l'aggiornamento del pacchetto fisso il problema è ancora esistente, a volte il modo più semplice per risolvere il problema è eliminare il catalogo vendor e aggiornare il compositore.