3

英語が下手で申し訳ありません。私はネイティブ スピーカーではありません。必要に応じて、テキストを自由に修正してください。

質問は非常に単純ですが (このテキストの最後にあります)、いくつかの調査とテストを行ってその根拠を書きました。

根拠

必要に応じて、この理論的根拠をスキップして、質問自体に直接ジャンプできます。

私は、Symfony2コンソールを使用doctrine:generate:entitiesして、逆側からManyToMany関係を維持しようと数時間試みてきました。doctrine:generate:crud

所有側からは、生成されたクラッドをそのまま使用して関係がデータベースに保存されますが、逆側からではありません (これは期待されます: http://docs.doctrine-project.org/en/2.0.x/ reference/association-mapping.html#owning-side-and-inverse-side )

私が望むのは、自動生成されたコントローラーを変更せずに、逆側からも機能させることです。モデル(エンティティ)だけを変更したい。

簡単な方法は、コントローラーにいくつかのカスタム コード行を追加することです。

// Controller that works the way I want
// Controller/AlunoController.php

...

public function createAction(Request $request)
{
    $entity  = new Aluno();
    $form = $this->createForm(new AlunoType(), $entity);
    $form->bind($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();

        // begin custom code
        foreach ($entity->getResponsaveis() as $responsavel) {
            $responsavel->addAluno($entity);
        }
        // end custom code

        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('aluno_edit', array('id' => $entity->getId())));
    }

    return array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ); 
}

...

前のコードは機能しますが、これらのコードのカスタム行は関係ロジックを参照し、エンティティ自体に集中する必要があるため、これは私が望むものではありません (そうでない場合は、これを更新するコントローラー全体に複製する必要があります)実在物)。

そこで、私が次に行ったことは、必要なロジックを実行するためにエンティティ ファイルのアダーとリムーバーを変更し、逆側と所有側の両方を自動的に更新するコードを追加することでした ( http://docs.doctrine-project.org/で推奨されているように) en/2.0.x/reference/association-mapping.html#picking-owning-and-inverse-sideおよびhttps://stackoverflow.com/a/7045693/1501575 )

// Entity/Aluno.php

...

/**
 * Add responsaveis
 *
 * @param \MyBundle\Entity\Responsavel $responsaveis
 * @return Aluno
 */
public function addResponsavei(\MyBundle\Entity\Responsavel $responsaveis)
{

    /* begin custom code */
    //var_dump('addResponsavei');
    $responsavel->addAluno($this);
    /* end custom code */

    $this->responsaveis[] = $responsaveis;
    return $this;
}

...

同じコードがコントローラーにある場合は機能するため、これは機能するはずですが、実際には機能しません。

問題は、コントローラーで実行Aluno##addResponsavei()されたときにメソッドが呼び出されないことです$form->bind($request)(最初のコードサンプルがあります) (その var_dump() 行でこれに気付きました。他のゲッターにも var_dumps を配置し、それらの他のメソッドは次のように呼び出されました)。正常)。

したがって、すべての通常のセッターは確かに内部$form->bind($request)で呼び出されますが、これはそうではありません。メソッド名は `doctrine:generate:entities' によって自動生成されたので、これは奇妙です。これにより、$form->bind() はすべてのセッター、ゲッター、およびアダーを呼び出す方法を知ることができると思いました。

質問

$form->bind() が adder メソッド (Aluno##addResponsavei()) を呼び出さないのはなぜですか?

doctrine:generate:crudメソッドの検出と実行を妨げている、従わない特別な命名規則はありますか?

解決

user1452962 からのコメントと、後で Elnur Abdurrakhimov からの回答に感謝します。動作するようになりました。実際には非常にシンプルです。

関係の逆側を保持するプロパティでオプション「by_reference」を false に追加するだけで、突然addResponsavei()呼び出されるようになりました。

// Form/AlunoType.php

...

$builder
        ->add('nome')
        ->add('cidade_natal')
        ->add('nascimento')
        ->add('email')
        ->add('endereco')
        ->add('nome_sem_acento')
        ->add('data_hora_cadastro')
        ->add('responsaveis', null, array('by_reference' => false))
        ->add('turmas', null, array('by_reference' => false))

...

このようにして、コントローラーから関係ロジックがなくなり、それが私が探していたものです。君たちありがとう。

4

1 に答える 1

9

加算器を呼び出すには、by_referenceオプションをに設定する必要があります。false

于 2013-02-27T10:18:32.497 に答える