web-dev-qa-db-ja.com

Yii2は、単一トランザクションでの単一保存呼び出しで関連レコードを保存します

Yii2では、複数の関連レコードを単一の保存呼び出しと単一のトランザクションにdbに保存するにはどうすればよいですか。 2つのテーブルがあります。

User - id, name
UserAddress - id , user_id , city

Userテーブルには、UserAdressテーブルと1対多の関係があります

私がやりたいことは:

UserAddress ua = new UserAddress();
ua.city = "fff"

User u = new User();
u.name = "test";
u.userAddress = new Array(ua);
u.save();

ユーザーの保存を呼び出すと、user_idをuser.idに設定したユーザーとユーザーアドレスも保存する必要があります。

22
Gaurav Singla
 // You need create hasMany relation 'userAddress' (look guide relations)

$transaction = Yii::$app->db->beginTransaction();

try {

    $user = new User();
    $user->name = 'Name';
    $user->save();

    $ua = new UserAddress();
    $ua->city = 'City';

    $user->link('userAddress', $ua); // <-- it creates new record in UserAddress table with ua.user_id = user.id

    $transaction->commit();

} catch (Exception $e) {

    $transaction->rollBack();

}
30

以前の回答に加えて、事前に定義された関係がなく、検証エラーを明示的に処理して機能するバリアントを提案します。

Yii::$app->db->transaction(function(){

    $user = new User();
    $user->name = 'Name';

    if( !$user->save() ){
        throw new Exception('Can\'t be saved user model. Errors: '. join(', ', $user->getFirstErrors()));
    }

    $userAddress = new UserAddress();
    $userAddress->city      = 'City';
    $userAddress->user_id   = $user->id;

    if( !$userAddress->save() ){
        throw new Exception('Can\'t be saved user address model. Errors: '. join(', ', $userAddress->getFirstErrors()));
    }

});

このコードにより、両方のレコードが確実に保存されます。モデルの1つを保存できない場合、検証エラーで例外がスローされます。

5
IStranger