Формы Symfony Generator, Doctrine и M: N

У меня есть базовая установка M: N с тремя таблицами: кандидатом, позицией и кандидатом.

Вот скриншот ERD из MySQL Workbench

http://dl.dropbox.com/u/180411/stackoverflow/erd.png

Теперь, перейдя от этого, давайте поговорим о формах. В стандартном мире генератора symfony у вас будет отдельный интерфейс CRUD для всех трех этих таблиц. Тем не менее, я не хочу иметь интерфейс CRUD для candidate_position .

Я хочу, чтобы для действий по созданию и редактированию интерфейса кандидата содержалось поле с несколькими вариантами выбора (выберите список, массив флажков, что угодно), которые создавали бы записи CandidatePosition как часть действий кандидата.

К коду

config / doctrine / schema.yml (Примечание: это не весь schema.yml, а только таблицы, обсуждаемые здесь)

 --- detect_relations: true options: type: InnoDB candidate: columns: id: type: integer(4) primary: true unsigned: true notnull: true autoincrement: true first_name: type: string(45) notnull: true last_name: type: string(45) notnull: true created_at: type: integer(4) unsigned: true relations: Positions: class: Position refClass: CandidatePosition local: candidate_id foreign: position_id position: columns: id: type: integer(4) primary: true unsigned: true notnull: true autoincrement: true name: type: string(45) relations: Candidates: class: Candidate refClass: CandidatePosition local: position_id foreign: candidate_id candidatePosition: tableName: candidate_position columns: candidate_id: type: integer(4) primary: true unsigned: true notnull: true position_id: type: integer(4) primary: true unsigned: true notnull: true indexes: fk_candidate_position_candidate1: fields: [candidate_id] fk_candidate_position_position1: fields: [position_id] 

приложения / бэкэнда / модули / кандидат / конфигурации / generator.yml

 generator: class: sfDoctrineGenerator param: model_class: Candidate theme: admin non_verbose_templates: true with_show: false singular: ~ plural: ~ route_prefix: candidate with_doctrine_route: true actions_base_class: sfActions config: actions: ~ fields: first_name: { label: First Name } last_name: { label: Last Name } created_at: { label: Created On } candidate_positions: {label: Positions} list: sort: [last_name, asc] filter: ~ form: display: "User": [first_name, last_name] "Applying For": [candidate_positions] fields : hide: [created_at] edit: ~ new: ~ 

Библиотека / форма / учение / candidateForm.class.php

 class candidateForm extends BasecandidateForm { public function configure() { unset( $this['created_at'] ); $this->widgetSchema['candidate_positions'] = new sfWidgetFormDoctrineChoice( array( 'multiple' => true, 'model' => 'Position', 'renderer_class' => 'sfWidgetFormSelectCheckbox' ) ); $this->validatorSchema['candidate_positions'] = new sfValidatorDoctrineChoice( array( 'multiple' => true, 'model' => 'Position', 'min' => 1 ) ); } } 

Все это работает, за исключением случаев, когда дело доходит до фактического сохранения данных. Это то место, где я застреваю.

Мне явно нужно что- то сделать, чтобы создавать / редактировать / удалять записи CandidatePosition, но я не уверен, с чего начать работать. В candidateActions ? Переопределить Basecandidate::save() ?

Сообщите мне, есть ли другие данные, которые вам могут понадобиться.

  • PHP 5.2.x
  • Symfony 1.4.3

Solutions Collecting From Web of "Формы Symfony Generator, Doctrine и M: N"

Около 10 месяцев назад у меня была аналогичная проблема с отношениями M: N и метаданных в таблице соединений.

Я нашел те записи блога Меликедева очень полезными! Это не совсем то же самое, что и ваш вариант использования, но он может дать вам несколько советов:

http://melikedev.com/2009/12/09/symfony-w-doctrine-saving-many-to-many-mm-relationships/

http://melikedev.com/2009/12/06/symfony-sfformextraplugin-select-double-list-maintain-order/

http://melikedev.com/2010/04/06/symfony-saving-metadata-during-form-save-sort-ids/

прежде всего, я могу предложить обновление версии Symfony – я использую 1.4.11, где вы будете работать с нуля.

Если это невозможно в вашем случае, лучшим местом для этого будет переопределение базового doSave () метода в кандидатеForm следующим образом:

 protected function doSave($con = null) { $existing = $this->object->Position->getPrimaryKeys(); $values = $this->getValue('candidate_positions'); $unlink = array_diff($existing, $values); $this->object->unlink('Position', array_values($unlink)); $link = array_diff($values, $existing); $this->object->link('Position', array_values($link)); parent::doSave($con); } 

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

 public function updateDefaultsFromObject() { parent::updateDefaultsFromObject(); if (isset($this->widgetSchema['candidate_positions'])) { $this->setDefault('candidate_positions', $this->object->Position->getPrimaryKeys()); } } 

Это должно сделать трюк.

ОБНОВИТЬ

Я думаю, что, так как обновление до 1.4.11 не помогает, есть некоторые проблемы с определением схемы, и я предполагаю, что вам нужно добавить определение отношения для ссылки на таблицу «preferPosition» следующим образом:

  relations: Candidate: class: Candidate local: candidate_id foreign: id foreignAlias: Candidates Position: class: Position local: position_id foreign: id foreignAlias: Positions 

Надеюсь это поможет.

С уважением.