获取最新保存的表单数据的ID

时间:2013-06-21 01:28:32

标签: symfony1 symfony-1.4

我有这个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错误,是否可以指向正确的方向?

1 个答案:

答案 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']);
  }
}