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()の最新の ID を取得する適切な方法がわからず、(Google と Stackoverflow の調査の後) 見つかりませんでした。SdrivingMaquina

これは、私の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 は複合キーの処理が得意ではないため、1 つのフィールドのみを使用する必要があります。一意性を確保する場合は、一意のインデックスを追加します。

外部キーには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_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']);
  }
}
于 2013-06-21T08:52:14.523 に答える