Tanmay
Tanmay

Reputation: 3159

How to save multiple related models at the same time

In my RegistrationController@store, I am doing the following:

I realized if one of these steps fails, for example if due to slow connectivity the profile is somehow not created, my app will break. Here is my store method:

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();
}

It is worth mentioning that, all of the data is coming from a registration form. How can I execute all these steps at a time (or, in one statement) so that if the statement executes successfully, I will have a perfectly synchronized registration, otherwise, no data will be persisted to the database?

Upvotes: 0

Views: 386

Answers (1)

Fatemeh Majd
Fatemeh Majd

Reputation: 739

Use transactions.

Before the first DB operation, in your case: User::create, use this:

DB::beginTransaction();

From now on, put all of your db operations in try/catch braces and if any exception happens, use:

DB::rollBack();

And at the end of the function, before return statement, put this:

DB::commit();

If you can have all your operations in the same place, it's easier to do this:

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

Upvotes: 1

Related Questions