我有一个基本的M:N设置,有三个表:候选,位置和candidate_position。
以下是MySQL Workbench的ERD截图
现在,继续我们谈论形式。在symfony生成器的默认世界中,您将为所有这三个表都有一个单独的CRUD接口。但是,我不希望candidate_position
拥有CRUD接口。
我想要的是,Candidate接口的创建和编辑操作包含一个多选字段(选择列表,复选框数组,等等),这些字段将创建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: ~
LIB /形式/教义/ 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()
?
如果您可能需要查看其他任何数据,请与我们联系。
答案 0 :(得分:1)
大约10个月前,我在连接表中遇到了M:N关系和元数据的类似问题。
我发现melikedev的那些博客条目非常有用!这与您的用例不完全相同,但它可能会给您一些提示:
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/
答案 1 :(得分:0)
首先我建议升级symfony版本 - 我使用1.4.11,你可以从头开始使用这个功能。
如果在你的情况下不可能,那么最好的地方是覆盖candidateForm中的基本doSave()方法,如下所示:
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的更新没有帮助,因此架构定义存在一些问题,我的猜测是您需要将关系定义添加到链接表'candidatePosition',如下所示:
relations:
Candidate:
class: Candidate
local: candidate_id
foreign: id
foreignAlias: Candidates
Position:
class: Position
local: position_id
foreign: id
foreignAlias: Positions
希望这有帮助。
问候。