0

我有这个 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()但不知道也没有找到(经过一些谷歌和 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 错误,任何可以指出我正确的方向吗?

4

1 回答 1

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 不太擅长处理复合键,因此您应该只使用一个字段。如果要确保唯一性,请添加唯一索引

您应该将外键命名为empresa_idnot 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_idsymfony 这样的外键字段将为其创建一个选择小部件,并且选择的值将自动保存。如果您不希望该小部件出现在表单中,则不应将其放入(或取消设置)并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 和学说),然后阅读 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']);
  }
}
于 2013-06-21T08:52:14.523 回答