我有这个schema.yml:
SdrivingMaquina:
connection: doctrine
tableName: sdriving_maquina
actAs: [Timestampable]
columns:
idmaquina: { type: integer(8), fixed: false, unsigned: false, primary: true, autoincrement: true }
idempresa: { type: integer(4), fixed: false, unsigned: true, primary: true, autoincrement: false }
patente: { type: string(12), fixed: false, unsigned: false, primary: false, notnull: true, autoincrement: false }
relations:
Empresa: { local: idempresa, class: SdrivingEmpresa, type: one, foreignType: one, foreignAlias: MaquinaEmpresa, onDelete: CASCADE, onUpdate: CASCADE }
SdrivingMaquinaEmisor:
connection: doctrine
tableName: sdriving_maquina_emisor
actAs: [Timestampable]
columns:
idmaquinaemisor: { type: integer(8), fixed: false, unsigned: false, primary: true, autoincrement: true }
idmaquina: { type: integer(8), fixed: false, unsigned: false, primary: true, autoincrement: false }
idemisor: { type: integer(8), fixed: false, unsigned: false, primary: true, autoincrement: false }
relations:
SdrivingEmisor: { onDelete: CASCADE, local: idemisor, foreign: idemisor, type: one }
SdrivingMaquina: { onDelete: CASCADE, local: idmaquina, foreign: idmaquina, type: one }
这是相关表单的configure()
方法:
public function configure() {
$this->current_user = sfContext::getInstance()->getUser()->getGuardUser();
unset($this['updated_at'], $this['created_at']);
$this->widgetSchema['idempresa'] = new sfWidgetFormInputHidden();
$id_empresa = $this->current_user->getSfGuardUserProfile()->getIdempresa();
$this->setDefault('idempresa', $id_empresa);
$this->widgetSchema['no_emisor'] = new sfWidgetFormDoctrineChoice(array('model' => 'SdrivingEmisor', 'add_empty' => 'Seleccione un Emisor', 'table_method' => 'fillChoice'));
$this->validatorSchema['idempresa'] = new sfValidatorPass();
$this->validatorSchema['no_emisor'] = new sfValidatorPass();
}
我正在尝试保存主maquina
然后保存关系SdrivingMaquinaEmisor()
的数据,但不知道并且没有找到(在Google和Stackoverflow研究之后)正确的方法获取SdrivingMaquina
对象的最新ID。
这就是我在save()
方法中所做的事情(在同一表格中):
public function save($con = null) {
$new_machine = parent::save($con);
$relation = new SdrivingMaquinaEmisor();
$relation->setIdmaquina($new_machine->getIdmaquina());
$relation->setIdemisor($this->values['no_emisor']);
$relation->save();
return $new_machine;
}
但是setIdmaquina()
永远不会得到一个值,所以它会破坏我的应用程序并导致CONSTRAINT错误,是否可以指向正确的方向?
答案 0 :(得分:1)
您不必这样做,不需要ID。如果表单正确并且表单中包含必填字段(idempresa
),则关系将自动保存。
这不是一个完全的答案(这取决于很多事情)你的问题,但我可以给你一些建议(我希望你不介意)。
让我们尝试简化一些事情:
SdrivingMaquina:
actAs:
Timestampable: ~
columns:
empresa_id: { type: integer(4), unsigned: true, primary: true }
patente: { type: string(12), notnull: true }
relations:
Empresa: { class: SdrivingEmpresa, type: one, foreignType: one, foreignAlias: MaquinaEmpresa, onDelete: CASCADE, onUpdate: CASCADE }
SdrivingMaquinaEmisor:
actAs:
Timestampable: ~
columns:
maquina_id: { type: integer, notnull: true }
emisor_id: { type: integer, notnull: true }
relations:
SdrivingEmisor: { onDelete: CASCADE, local: emisor_id, type: one }
SdrivingMaquina: { onDelete: CASCADE, local: maquina_id, type: one }
主键(如idmaquina
)不需要显式声明...主键将自动添加,为简单起见,它将(并且应该)命名为id。 Doctrine并不擅长处理复合键,所以你应该只使用一个字段。如果您想确保唯一性,请添加unique index。
您应该为empresa_id
而不是idempresa
命名外键,因为它会简化某些内容。
并且在表格中(我不知道这个表格属于哪个表格):
/** @var sfDoctrineGuardUser */
protected $user;
public function configure()
{
// user comes as an option e.g. in an action new SomeForm(null, array('user' => $this->getUser()));
$this->user = $this->getOption('user');
if ($this->user instanceof sfDoctrineGuard)
{
throw new InvalidArgumentException('A sfDoctrineGuard object is required as "user" option in '.__METHOD__);
}
// use useFields instead of unset
$this->useFields(array(
'empersa_id',
'no_emisor',
// ...
));
// this should be done automatically by symfony in the base class
//$this->widgetSchema['idempresa'] = new sfWidgetFormInputHidden();
//$id_empresa = $this->current_user->getSfGuardUserProfile()->getIdempresa();
//$this->setDefault('idempresa', $id_empresa);
// do not recreate widgets if not needed (I don't know if no_emisor is in the schema or not), just modify them
$this->getWidget('no_emisor')->setOption('table_method', 'fillChoice');
$this->getWidget('no_emisor')->setOption('add_empty', 'Seleccione un Emisor');
}
如果架构正确并且empresa_id
之类的外键字段位于symfony形式,则会为其创建一个选择窗口小部件,并且将自动保存所选值。如果您不希望表单中包含该窗口小部件,则不应将其放入(或取消设置)并在代码中设置字段值empresa_id
。您应该覆盖doUpdateObject
方法:
protected function doUpdateObject($values)
{
parent::doUpdateObject($values);
// thats it... link objects together and doctrine will figure out the id
$this->getObject()->setEmpresa($this->user);
}
您应该遵循惯例和最佳做法(从文档中获取)。这不仅仅是因为您的代码对于其他人来说更具可读性和可理解性,但它会让您的生活更轻松。我知道学习像symfony这样复杂的东西需要花费很多时间,但你应该阅读所有的文档(对于symfony和doctrine),然后阅读symfony的代码本身,以了解它是如何工作的。使用框架简化您的工作,不要使其复杂化。
<强>更新强>:
这是在保存之前将对象链接在一起的方法(使用此类或类似的东西而不是save
方法):
protected function doUpdateObject($values)
{
parent::doUpdateObject($values);
if (isset($this['no_emisor']))
{
if ($this->isNew())
{
$sdrivingMaquinaEmisor = new SdrivingMaquinaEmisor();
$this->getObject()->setSdrivingMaquinaEmisor($sdrivingMaquinaEmisor);
}
else
{
$sdrivingMaquinaEmisor = $this->getObject()->getSdrivingMaquinaEmisor();
}
$sdrivingMaquinaEmisor->setIdemisor($this->values['no_emisor']);
}
}