У меня есть базовая установка M: N с тремя таблицами: кандидатом, позицией и кандидатом.
Вот скриншот ERD из MySQL Workbench
Теперь, перейдя от этого, давайте поговорим о формах. В стандартном мире генератора 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()
?
Сообщите мне, есть ли другие данные, которые вам могут понадобиться.
Около 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
Надеюсь это поможет.
С уважением.