2016-01-08 2 views
8

Ich habe eine "Aufgaben" -Tabelle, die auf eine "Estados" -Tabelle mit einem Fremdschlüssel aus Spalte Tasks.taskestado zu Estados.estado verweist.symfony3: Formular für Entität erstellen, die über eine Spalte mit vielen zu einer Beziehung verfügt

Hier ist die relevante XML-Mapping für Aufgaben:

<entity name="AppBundle\Entity\Tasks" table="TASKS" repository-class="AppBundle\Repository\TasksRepository"> 
<id name="taskid" type="bigint" column="TaskID"> 
    <generator strategy="IDENTITY"/> 
</id> 
... 
<many-to-one field="taskestado" target-entity="Estados" fetch="LAZY"> 
    <join-columns> 
    <join-column name="TaskEstado" referenced-column-name="Estado"/> 
    </join-columns> 
</many-to-one> 
... 

Und für Estados:

<entity name="AppBundle\Entity\Estados" table="ESTADOS"> 
<id name="estado" type="string" column="Estado" length="15"> 
    <generator strategy="IDENTITY"/> 
</id> 
<field name="estadodescricao" type="string" column="EstadoDescricao" length="50" nullable="true"> 
    <options> 
    <option name="fixed"/> 
    </options> 
</field> 
... 

dies gegeben, ich versuche, eine Aktion (novaAction()) Aufgaben zu schaffen zu machen. Hier ist der Controller-Code:

public function novaAction(Request $request) 
{ 
    $task = new Tasks(); 
    $em = $this->getDoctrine()->getManager(); 

    dump($task); 
    #$task->setTaskEstado(new Estados()); 
    $form = $this->createForm(TasksType::class, $task); 
    $form->handleRequest($request); 

    if ($form->isSubmitted()) { 
     if ($form->isValid()) { 
      // Criar a tarefa na BD 
      $em->persist($form->getData()); 
      $em->flush(); 
      $this->addFlash('notice', 'app.nova_tarefa.mensagem_sucesso'); 

      return $this->redirectToRoute('nova_tarefa'); 
     } 

     $this->addFlash('error', 'app.nova_tarefa.mensagem_erro'); 
    } 

und der relevante TasksType Code:

class TasksType extends AbstractType 
{ 

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('taskid', HiddenType::class) 
     ... 
     #->add('taskestado') 
     ->add('taskestado', EntityType::class, [ 'class' => 'AppBundle:Estados' ]) 
     ... 
} 

/** 
* @param OptionsResolver $resolver 
*/ 
public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'AppBundle\Entity\Tasks', 
     #'empty_data' => function (\Symfony\Component\Form\FormInterface $form) { 
     # #return new Tasks($form->get('tasks')->getData()); 
     # return new Tasks(); 
     #}, 
    )); 
} 
} 

Die 'empty_data' Option war ein Versuch, die Form ohne Umweg eine Instanz von Aufgaben, um es zu schaffen. Auch habe ich das gleiche Ergebnis, wenn ich Taskedado mit dem kommentierten Code, ich. e., ohne Argumente.

Und hier ist die entsprechende Einheit Aufgaben:

namespace AppBundle\Entity; 

use Doctrine\Common\Collections\ArrayCollection; 

/** 
* Tasks 
*/ 
class Tasks 
{ 
    /** 
    * @var integer 
    */ 
    protected $taskid; 

    /** 
    * @var \AppBundle\Entity\Estados 
    */ 
    protected $taskestado; 

    ... 

    /** 
    * Get taskid 
    * 
    * @return integer 
    */ 
    public function getTaskid() 
    { 
     return $this->taskid; 
    } 

    /** 
    * Set taskestado 
    * 
    * @param \AppBundle\Entity\Estados $taskestado 
    * 
    * @return Tasks 
    */ 
    public function setTaskestado(\AppBundle\Entity\Estados $taskestado = null) 
    { 
     $this->taskestado = $taskestado; 

     return $this; 
    } 

    /** 
    * Get taskestado 
    * 
    * @return \AppBundle\Entity\Estados 
    */ 
    public function getTaskestado() 
    { 
     return $this->taskestado; 
    } 

    ... 
} 

Wenn ich die Seite zu öffnen, bekomme ich folgende Fehlermeldung:

Entities passed to the choice field must be managed. Maybe persist them in the entity manager?

Ich würde auch die CRUD erzeugt (bin/console doctrine:generate:crud --filter=Tasks), so dass Ich könnte überprüfen, wie es gemacht wird, aber der Code ist ähnlich, ebenso wie die Ergebnisse (nachdem einige Probleme im TasksType für einige Datetime-Spalten behoben wurden).

Was mache ich falsch?

+0

Haben Sie Code in Ihrer 'Task' Entität, der den' Taskestado' automatisch initialisiert? – xabbuh

+0

Bevor ich den Code von mblaettermann hinzufüge, hatte ich sogar die Funktion __construct() nicht. –

+0

Können Sie trotzdem den Code dieser Entitätsklasse anzeigen? – xabbuh

Antwort

2

Ich habe endlich eine Antwort auf diese, es war alles andere als offensichtlich.

Wie ich in der Frage gesagt habe, gibt es eine viele-zu-eins-Beziehung von Tasks.taskestado zu Estados.estado. Estados.estado ist eine Zeichenfolge, die Nullable sein kann, eine leere Zeichenfolge oder (normalerweise) eine nicht leere Zeichenfolge. Obwohl in der Zuordnung nicht angegeben, ist die leere Zeichenfolge der Standardwert für Taskestado.

Ich habe bereits Daten in der Tabelle, und einer der Einträge für Estados.estado ist genau die leere Zeichenfolge.

Ich habe nicht in der Frage abgeben, aber ich sah die folgenden Informationen in dem Stack-Trace dieser Ausnahme:

[1] Symfony\Component\Form\Exception\RuntimeException: Entities passed to the choice field must be managed. Maybe persist them in the entity manager? 
    at n/a 
     in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php line 119 

    at Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader->getIdValue(object(Estados)) 
     in line 

    at call_user_func(array(object(IdReader), 'getIdValue'), object(Estados)) 
     in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php line 204 

    at Symfony\Component\Form\ChoiceList\ArrayChoiceList->flatten(array(object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados)), array(object(IdReader), 'getIdValue'), array(), array(), array()) 
     in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php line 91 

So abgerufen die EntityType die Werte aus der Datenbank und versuchen, sie zu machen, . Mit anderen Worten, sie waren bereits bestehen und das Problem konnte nicht wirklich darin liegen, wie ich die Entität initialisierte.

Also erinnerte ich mich an den leeren String-Wert für die Estados-Entität und versuchte, es aus der Datenbank zu entfernen: Problem gelöst, die TaskEstado-Entität wurde initialisiert und wie erwartet gerendert.

Jetzt brauche ich einen Weg um dies zu umgehen, aber die Lösung wurde gefunden.

Vielen Dank für Ihre Antworten.

3

Wie der Fehler sagt, müssen Sie in Ihren Mappings für Tasks cascade = persist setzen. Zum Beispiel:

<many-to-one field="taskestado" target-entity="Estados" fetch="LAZY"> 
    <cascade> 
    <cascade-persist/> 
    </cascade> 
    <join-columns> 
    <join-column name="TaskEstado" referenced-column-name="Estado"/> 
    </join-columns> 
</many-to-one> 

Auch Statt tun $em->persist($form->getData()); Verwenden $em->persist($task);

sehen, ob das funktioniert ...

+0

Vielen Dank für Ihre Hilfe, aber das hat nicht funktioniert. –

1

Stellen Sie sicher, die Sie haben

$this->taskestado = new ArrayCollection(); 

im __construct() Ihrer Tasks Klasse.

Dann 2 Hinweise:

Versuchen Sie, nur Englisch in Ihrem Code zu verwenden. Auf diese Weise erhalten Sie viel mehr Antworten. als „best practice“ Verwendung Singulars für Ihre Namen Entitätsklasse Wie Task, TaskEstado

+0

Danke oder deine Antwort. Leider hat es nicht funktioniert, und ich habe immer noch genau das gleiche Problem. Laut symfony-Vorschlag habe ich ArrayCollection aus dem Namespace "Doctrine \ Common \ Collections \" verwendet. Der englische Teil ist meine Schuld, auch wenn der Originalcode nicht in Englisch ist. Über den Singular/Plural ist das schwieriger, da der Tisch vor einigen Jahren nicht gebaut wurde. Ich habe wenig bis gar keine Kontrolle über die Tabellennamen. –

+0

Dies ist auch eine ManyToOne-Beziehung. Soweit ich weiß, scheint Ihre Lösung nur für eine OneToMany-Beziehung gültig zu sein. –

+0

Sie können Tabellennamen, die in SQL verwendet werden, separat mit @Table Annotation – mblaettermann

Verwandte Themen