如何同时保存多个相关模型

时间:2017-12-26 08:23:02

标签: php laravel eloquent

在我的RegistrationController @ store中,我正在执行以下操作:

  • 创建用户(用户:hasMany()积分,hasOne()个人资料,belongsToMany()角色)
  • 附加角色(角色:belongsToMany()用户)
  • 创建个人资料(个人资料:belongsTo()用户)
  • 将初始分数设为0(积分:belongsTo()用户)

我意识到如果其中一个步骤失败,例如,如果由于连接速度慢导致配置文件无法以某种方式创建,我的应用程序将会中断。这是我的商店方法:

public function store(){
    $profile = new Profile();
    $points = new Points();
    $this->validate(request(),[
        'name' => 'required',
        'username' => 'required|unique:users',
        'email' => 'required|email|unique:users',
        'password' => 'required|confirmed',
        'role_id' => 'required|between:1,2'
    ]);

    $user = User::create([
        'name' => request('name'),
        'username' => request('username'),
        'email' => request('email'),
        'password' => bcrypt(request('password'))
    ]);

    $role_student = Role::where('title', 'Student')->first();
    $role_parent = Role::where('title', 'Parent')->first();
    if(request()->input('role_id') == 1){
        $user->roles()->attach($role_student);
    } else if(request()->input('role_id') == 2){
        $user->roles()->attach($role_parent);
    }

    $profile->user_id = $user->id;
    $profile->date_of_birth = Carbon::createFromDate(request('year'),request('month'),request('day'));
    $profile->institution = request('institution');
    $profile->class = request('class');
    $profile->division = request('division');
    $profile->photo = 'propic/default.png';
    $profile->bio = 'I am a Member!';
    $profile->social_link = 'http://facebook.com/zuck';
    $profile->save();
    auth()->login($user);
    \Mail::to($user)->send(new Welcome($user));
    $points->updateOrCreateAndIncrement(0);
    return redirect()->home();
}

值得一提的是,所有数据都来自注册表。如何一次执行所有这些步骤(或者,在一个语句中),这样如果语句成功执行,我将完全同步注册,否则,数据库不会持久存储?

1 个答案:

答案 0 :(得分:1)

使用交易。

在第一个数据库操作之前,在你的情况下:User :: create,使用它:

DB::beginTransaction();

从现在开始,将所有数据库操作放在try / catch括号中,如果发生任何异常,请使用:

DB::rollBack();

在函数结束时,在return语句之前,输入:

DB::commit();

如果您可以将所有操作放在同一个地方,则可以更轻松地执行此操作:

DB::transaction(function () {
  //all your db opertaions
}, 2);