2016-07-15 14 views
2

私は2モデル:ReceivedGoodsDetailStockInventoryを持っています。ストアドプロシージャを使用して複数のテーブルに保存

ReceivedGoodsDetailの場合は、StockInventoryも自動的にテーブルStockInventoryに挿入されます。

私は、この私が試したものを、このストアドプロシージャを使用します。

public function actionCreate($id) { 
$model = new ReceivedGoodsDetail(); 
$connection = \Yii::$app->db; 
$transaction = $connection->beginTransaction(); 

$model->ID_Received_Goods = $id; 
if ($model->load(Yii::$app->request->post()) && $model->validate()) { 
$connection = Yii::$app->db; 
$command = $connection->createCommand('{call usp_T_Received_Goods_Detail#InsertData(:ID_Received_Goods,:ID_Item, :Qty, :User)}'); 

$ID_Received_Goods = $model->ID_Received_Goods; 

$ID_Item = $model->ID_Item; 
$Qty = $model->Qty; 
$User = Yii::$app->user->identity->username; 

$command->bindParam(":ID_Received_Goods",$ID_Received_Goods,PDO::PARAM_STR); 
$command->bindParam(":ID_Item", $ID_Item, PDO::PARAM_STR); 
$command->bindParam(":Qty", $Qty, PDO::PARAM_INT); 
$command->bindParam(":User", $User, PDO::PARAM_STR); 

if ($command->execute() == 0) { 
$transaction->commit(); 
} else { 
$transaction->rollBack(); 
foreach ($model->getErrors() as $key => $message) { 
Yii::$app->session->setFlash('error', $message); 
} 
} 

return $this->redirect(['receivedgoodsheader/view', 'id' => $model->ID_Received_Goods]); 
} else { 
return $this->render('create', [ 
'model' => $model, 
]); 
} 
} 

をしかし

+1

問題は何ですか?私はそれを得ることはありません – yafater

答えて

0

上記の場合と同様に使用2つのモデルは、そのようなことを行うことを恐れてはいけない場合、私は混乱しています、ここではストアドプロシージャを使うのは悪いことではありません。しかし、一般的にあなたのコードはきれいではなく、かなり混乱しています。

まず、ストアドプロシージャを使用している場合、なぜReceivedGoodsDetail(INSTERT)のトリガーを作成しないのですか? IMHOはトリガーでもっと簡単になります。

ここでは、実装に関するいくつかの注意点があります。

  1. なぜ最初に取引を開きますかif?検証に失敗すると、トランザクションは手動で終了しません 。
  2. 私はここで2つのモデルを使用して見ることができません - ReceivedGoodsDetailStockInventory 私は理解できるようにストアドプロシージャusp_T_Received_Goods_Detail#InsertDataで作成されますか?
  3. トランザクションが失敗しても、ユーザーをアイテムビューにリダイレクトするのはなぜですか?
  4. ActiveRecordを使用しています。次に、トランザクションを手動で開始する必要はありません。ちょうど の操作を、transactions()メソッドでこのモデルのトランザクションにしたいと定義してください。
  5. ActiveRecordを使用しています。アプリケーションではなく、モデルクラスからDB接続を取得する方が良い方法です。 デフォルトではYii::$app->dbになりますが、後で簡単にこの特定のモデルの接続を変更することができます。 ReceivedGoodsDetailため

(例えば)あなたは(もしまだ)のActiveRecordを拡張することは良くなると過負荷insertInternal()方法 。クラスReceivedGoodsDetail

public function transactions() { 
    return [ 
     'default' => self::OP_INSERT 
    ];  
} 

protected function insertInternal($attributeNames = null) { 
    if (!$this->beforeSave(true)) { 
     return false; 
    } 
    $values = $this->getDirtyAttributes($attributes); 

    /* overrided part of code */ 

    $connection = static::getDb(); 
    $command = $connection->createCommand('{call usp_T_Received_Goods_Detail#InsertData(:ID_Received_Goods,:ID_Item, :Qty, :User)}'); 

    $ID_Received_Goods = $model->ID_Received_Goods; 

    $ID_Item = $model->ID_Item; 
    $Qty = $model->Qty; 
    $User = Yii::$app->user->identity->username; 

    $command->bindParam(":ID_Received_Goods",$ID_Received_Goods,PDO::PARAM_STR); 
    $command->bindParam(":ID_Item", $ID_Item, PDO::PARAM_STR); 
    $command->bindParam(":Qty", $Qty, PDO::PARAM_INT); 
    $command->bindParam(":User", $User, PDO::PARAM_STR); 

    if($command->execute() != 0) { 
     return false; 
    } 

    /* end of overrided part */ 

    $changedAttributes = array_fill_keys(array_keys($values), null); 
    $this->setOldAttributes($values); 
    $this->afterSave(true, $changedAttributes); 

    return true; 
} 

あなたのアクションで:

public function actionCreate($id) { 
    $model = new ReceivedGoodsDetail(); 

    $model->ID_Received_Goods = $id; 
    if ($model->load(Yii::$app->request->post()) && $model->save(true)) { 
     return $this->redirect(['receivedgoodsheader/view', 'id' => $model->ID_Received_Goods]); 
    } else { 
     foreach ($model->getErrors() as $key => $message) { 
      Yii::$app->session->setFlash('error', $message); 
     } 
     return $this->render('create', [ 
      'model' => $model, 
     ]); 
    } 
} 

そしてフォームを作成する上であなたのフラッシュメッセージをキャッチ。

P.S.もう一つの瞬間。 path/to/model/{id}エンドポイント と定義済みのIDを使用して新しいインスタンスを作成するのは奇妙なことです。通常これはPOST path/to/modelのように見えます。しかし、これはビジネスロジックの対象となる可能性があるので、改善できるかどうかは分かりません。

P.P.Sこの例はテストされていません(明らかに)ので、ここでいくつかの間違いがあります。

関連する問題