У меня проблема со встроенной формой из модели, которая имеет отношение многие ко многим. Встроенная форма сохранит модель правильно, но не сохранит отношения многие ко многим.

Примере:

Schema.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. Я могу редактировать любимые цвета, но форма больше не встроена...

2
Charles 26 Мар 2011 в 12:00

1 ответ

У меня была та же проблема, что и у вас. Билет #5867 в symfony посвящен этой проблеме, и многие люди потеряли много времени с ним.

В билете некоторые люди дают решения. Вы можете попробовать их, но я не знаю, почему они не сработали в моем случае.

Мне удалось найти решение, найденное в этом сообщении. . Это очень полезный пост, в котором объясняется причина этой ошибки и обходной путь.

В основном ошибка связана с тем, что при сохранении встроенных форм 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)
}

Некоторые люди говорят, что у них есть какая-то проблема в комментариях к посту, и предлагают решение, но это был не мой случай.

Надеюсь, это кому-нибудь поможет, даже если мой ответ на довольно старый открытый вопрос.

1
Waiting for Dev... 7 Янв 2012 в 20:58
Спасибо, очень полезный ваш комментарий. Я не фанат обновления ядра symfony, надеюсь, что выйдет исправление... Больше не могу его найти, но думаю, что решил эту проблему, сохранив его самостоятельно в родительской форме (MotherForm в моем примере).
 – 
Charles
9 Янв 2012 в 03:13