2016-01-08 22 views
8

私はTasks.taskestadoからEstados.estadoまでの外部キーを持つ "Estados"テーブルを参照する "Tasks"テーブルを持っています。ここでsymfony3:多対1の関係を持つ列を持つエンティティのフォームを作成する

は、タスクに関連するXMLマッピングです:

<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> 
... 

そして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> 
... 

はこのことを考えると、私は、タスクを作成するためのアクション(novaActionを())を作成しようとしています。 「empty_data」オプションがそれにタスクのインスタンスを渡さずにフォームを作成しようとした

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(); 
     #}, 
    )); 
} 
} 

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'); 
    } 

、関連TasksTypeコード: はここにコントローラー・コードです。 また、taskestadoをコメント付きのコードで追加すると同じ結果になります。すなわち、引数なし。

そして、ここでは関係タスクエンティティです:私は、ページを開くと

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

    ... 
} 

、私は次のエラーを取得する:

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

ように、私はまた、CRUD(bin/console doctrine:generate:crud --filter=Tasks)を生成したいです私はそれがどのように行われたかを確認することができますが、コードは似ていますが、結果は(いくつかのdatetime列のTasksTypeのいくつかの問題を修正した後)です。

私は間違っていますか?

+0

'task'エンティティに' taskestado'を自動的に初期化するコードがありますか? – xabbuh

+0

mblaettermannのコードを追加する前に、私も__construct()関数を持っていませんでした。 –

+0

それにもかかわらず、そのエンティティクラスのコードを表示できますか? – xabbuh

答えて

2

私はようやく答えを得ました。

私が質問したように、Tasks.taskestadoからEstados.estadoまでは多対1の関係があります。 Estados.estadoは文字列であり、null可能、空の文字列、または空ではない文字列です。マッピングには示されていませんが、空の文字列はtaskestadoのデフォルト値です。

私は既にテーブルにデータがあり、Estados.estadoのエントリの1つは空の文字列です。

私は疑問に投稿していなかったが、私はこの例外のスタックトレースに以下の情報を見た:だから

[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 

は、EntityTypeは、データベースから値を取得し、それらをレンダリングしようとしていました。言い換えれば、それらはすでに永続化されており、エンティティをどのように初期化したかに問題は本当に存在しませんでした。

したがって、私はEstadosエンティティの空の文字列値を思い出し、データベースから削除しようとしました。問題が解決し、TaskEstadoエンティティが初期化され、期待通りにレンダリングされました。

これを回避する方法が必要ですが、解決策が見つかりました。

ありがとうございました。

3

エラーとして、Tasksのマッピングでcascade = persistを設定する必要があります。また、代わりにそれが動作するかどうかを参照してください$em->persist($form->getData()); 使用$em->persist($task);

をやっ

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

...

+0

ありがとう、助けてもらえませんでした。 –

1

はあなたの__construct()

$this->taskestado = new ArrayCollection(); 

れていることを確認します。たとえば、 Tasksクラス。

次に2つの通知:

コード内で英語のみを使用してください。このようにして、より多くの反応を得ることができます。 "ベストプラクティス"として、あなたのエンティティクラス名にSingularsを使用してください。Taskのように、TaskEstado

+0

ありがとう、またはあなたの答えです。 残念ながら、それはうまくいかず、私はまったく同じ問題を抱えています。 symfonyの提案に従って、私は名前空間 "Doctrine \ Common \ Collections \"からArrayCollectionを使用しました。 オリジナルのコードが英語でなくても、英語の部分は私のせいです。 単数形/複数形については、それは数年前にテーブルが造られた方法ではないので、より難しいです。私はテーブル名をほとんど制御することはできません。 –

+0

また、これはManyToOne関係です。私が知っていることから、あなたのソリューションはOneToMany関係にのみ有効であるようです。 –

+0

@Tableを使用してSQLで使用するテーブルのネームを別々に制御することができます。注釈 – mblaettermann

関連する問題