2

多対多の関係を持つモデルからの埋め込みフォームに問題があります。埋め込みフォームはモデルを正しく保存しますが、多対多の関係は保存しません。

例:

スキーマ.yml:

Mother:
  columns:
    name:
      type: string(80)

Color:
  columns:
    name:
      type: string(80)

Child:
  columns:
    mother_id:
      type: integer
    name:
      type: string(80)
  relations:
    Mother:
      class: Mother
      local: mother_id
      foreign: id
      type: one
      onDelete: cascade
      foreignType: one
      foreignAlias: Children
    FavoriteColors:
      class: Color
      refClass: ChildColor
      local: child_id
      foreign: color_id
      onDelete: cascade
      foreignAlias: Children

ChildColor:
  columns:
    child_id:
      type: integer
    color_id:
      type: integer

次に、MotherForm.class.php を変更します。

class MotherForm extends BaseMotherForm
{
  public function configure()
  {
    $this->embedForm('child', new ChildForm($this->getObject()->getChildren()));
  }
}

および ChildForm.class.php:

class ChildForm extends BaseChildForm
{
  public function configure()
  {
    unset($this['mother_id']);
  }
}

私はドクトリンでモジュールを生成します:

php symfony doctrine:generate-module frontend mother Mother

いくつかの色データを入れます:

Color:
  Color_1:
    name: blue
  Color_2:
    name: red
  Color_3:
    name: green
  Color_4:
    name: purple

/frontend_dev.php/mother/new を呼び出すと、新しい名前を追加できます。母と子の名前は更新されますが、お気に入りの色は保存されません...

phpmyadmin を使用して色と子の間に関係を追加し、次に /edit を呼び出すとします。次に、選択した複数選択に正しい色がありますが、編集できません。

Symfony のバグですか、それとも何か他のことをする必要がありますか?

更新: モデル Child のモジュールを生成するとします。好きな色を編集できるのですが、フォームが埋め込まれなくなりました...

4

1 に答える 1

1

私はあなたと同じ問題を抱えています。symfony のチケット #5867はすべてこの問題に関するものであり、多くの人がこの問題で多くの時間を失いました。

チケットでは、解決策を提供する人もいます。それらを試すことはできますが、私の場合はなぜうまくいかなかったのかわかりません。

この投稿にある解決策で成功しました。これは、このバグの理由と回避策を説明する非常に役立つ投稿です。

基本的に、バグは、埋め込みフォームを保存するときに、symfony がsave()埋め込みオブジェクトで呼び出しますが、埋め込みフォームでsave()はなく、オブジェクトで関連するテーブルを更新しないという事実によるものです。

それを解決するには、上書きする必要があります//lib/form/doctrine/BaseFormDoctrine.class.php(または同等の Propel ですが、次のコードで Doctrine を Propel に置き換えます):

bindEmbeddedForms()この方法で関数を作成します。

public function bindEmbeddedForms($embedded_forms, $values)
{
  if($this->isValid())
  {
    foreach ($embedded_forms as $name => $form)
    {
      $form->isBound = true;
      $form->values = $values[$name];

      if ($form->embeddedForms)
      {
        $this->bindEmbeddedForms($form->embeddedForms, $values[$name]);
      }
    }
  }
}

bind()この方法で親を呼び出す関数を宣言します。

public function bind(array $taintedValues = null, array $taintedFiles = null)
{
   parent::bind($taintedValues, $taintedFiles);
   $this->bindEmbeddedForms($this->embeddedForms, $this->getValues());
}

そして、このように上書きsaveEmbeddedForms()します:

public function saveEmbeddedForms($con = null, $forms = null)
{
  if (is_null($con))
  {
    $con = $this->getConnection();
  }

  if (is_null($forms))
  {
    $forms = $this->embeddedForms;
  }

  foreach ($forms as $key => $form)
  {
    if ($form instanceof sfFormDoctrine)
    {
      if(method_exists(new $form(), 'doSaveManyToMany'))
      {
        $form->doSaveManyToMany($con);
      }
      else
      {
        $form->getObject()->save($con);
      }
      $form->saveEmbeddedForms($con);
    }
    else
    {
      $this->saveEmbeddedForms($con, $form->getEmbeddedForms());
    }
  }
}

次に、埋め込みフォーム クラス (投稿ではBaseFormDoctrineクラスでもこれを行いますが、私のやり方ではよりクリーンだと思います) で、doSaveManyToManyリレーションを保存するメソッドを作成します。

public function doSaveManyToMany($con = null)
{
  if (is_null($con))
  {
    $con = $this->getConnection();
  }

  $this->object->save($con);
  /*
  * Save the many-2-many relationship
  */
  $this->save***List($con); //Ex: $this->saveAhasBList($con)
}

投稿のコメントに問題があり、解決策を言う人もいますが、私の場合はそうではありませんでした。

私の答えがかなり古い未解決の質問に対するものであっても、それが誰かの役に立てば幸いです。

于 2012-01-06T12:04:54.453 に答える