Форма Symfony / propel, сохраняющая объект с дополнительными свойствами - PullRequest
3 голосов
/ 19 августа 2011

Во-первых, позвольте мне сказать, что я нахожу интерфейс формы sfFormPropel несовместимым.Существует bind(), который ничего не возвращает, но запускает проверку, save(), который возвращает сохраненный объект, и bindAndSave(), который возвращает логическое значение, фактически возвращаемое значение isValid().Теперь у меня есть работающее приложение, но я не чувствую, что код правильный, и я совершенно новичок в symfony, поэтому, возможно, я что-то упускаю.

Объект, который мне нужно создатьнужны некоторые внешние свойства, которые не представлены в форме, являются внешними по отношению к модели и обрабатываются приложением (например, userId пользователя, который создал сущность, guid, сгенерированный извне и т. д.).

Прямо сейчас поток выглядит следующим образом:

  • получить значения из запроса и связать их с формой
  • проверить, является ли форма действительной
  • , еслиэто допустимо, добавьте дополнительные значения и свяжите их, чтобы сформировать еще раз
  • сохранить форму и вернуть объект

Очевидный ответ - добавить значения, специфичные для приложения,извлекается из запроса, но Не имеет смысла связывать специфичные для приложения значения, если форма недопустима, поскольку они могут быть потенциально дорогостоящими операциями, могут создавать записи в базе данных и т. д. Кроме того, это не должноможно передать эти значения с помощью запроса post, они должны поступать только из приложения.

Теперь я решил, что модель должна выполнять эти функции, но поскольку данные являются внешними по отношению к модели, действиееще нужно передать его модели.Проблема в том, что если я позвоню $form->getObject() после bind(), у него останутся старые данные, а не отправленные данные.

Как правильно реализовать этот вид постобработки?

Вторая награда начата, чтобы наградить другого ценного ответа

Ответы [ 2 ]

2 голосов
/ 22 августа 2011

Правильным способом будет установка значений по умолчанию для объекта, который вы передаете конструктору формы.Например, если вы хотите установить идентификатор зарегистрированного пользователя для создаваемого объекта:

$article = new Article();
$article->setUserId($this->getUser()->getId());
$form = new ArticleForm($article);
if ($request->isMethod('post')) {
  $form->bind($request->getParameter('article'));
  if ($form->isValid()) {
    $form->save();
  }
}

Аналогично для существующего объекта, вы можете загрузить запись и изменить любые свойства перед передачей ее конструктору формы.

РЕДАКТИРОВАТЬ:

Если вы хотите изменить объект после проверки, вы можете использовать $ form-> updateObject (), как предлагает Град в своем ответе.Если сгенерированные значения зависят от отправленных значений, вы можете переопределить sfFormObject :: processValues ​​():

class UserForm {

  public function processValues($values) {
    $values['hash'] = sha1($values['id'] . $values['username']);
    return parent::processValues($values);
  }

}

Если вам нужно что-то из действия, вы всегда можете передать его в качестве опции в форму:

$form = new UserForm($user, array('foo' => $bar));

Таким образом, вы можете использовать $ this-> getOption ('foo') в любом месте кода вашей формы, например.в processValues ​​().

1 голос
/ 22 августа 2011

Это отчасти зависит от того, кто обладает «знаниями» о дополнительных атрибутах. Если они действительно специфичны для конкретного запроса, то есть должны обрабатываться в контроллере, я иду на связывание, проверяю, действителен ли, а затем обновляю связанный объект. Чтобы получить обновленный объект со связанными (и проверенными) полями, используйте функцию updateObject.

$form->bind(..)
if ($form->isValid()) {

   $obj = $form->updateObject(); // Updates the values of the object with the cleaned up values. (returns object)
   $obj->foo = 'bar';

   $obj->save();
}

Но так как это обычно также поведение, специфичное для формы, я обычно переопределяю класс Form. Переопределив функцию doUpdateValues(), вы можете легко получить доступ к отправленным данным и добавить свои собственные данные. Конечно, вы также можете пойти выше в цепочке и переопределить функцию save(). Чтобы установить пользовательские данные для этой формы, вы также можете «опубликовать» публичные методы, которые затем могут использоваться контроллером.

...