Scooby's avatar

Save Model into two databases

I'm trying to save (as well as update) a user model into multiple databases but just can't figure out what's going wrong. This first part works fine:

$user = User::find(1);
$user->name = 'Test';
$user->save();

But what's going wrong with this bit here?

$user->setConnection('testing')->save();

Not getting any errors just nothing is stored to the "testing" database. Any ideas what needs adjusting?

0 likes
5 replies
Sergiu17's avatar
// Clone the model into a new, non-existing instance.
$user->replicate()->setConnection('testing')->save();

I use this

Snapey's avatar

your model is no longer 'dirty' and does not need saving

1 like
Scooby's avatar

@snapey Yeah I figured something like this was going on, just didn't know how to get around it. The end goal is to keep the two databases in sync so I'd want to store the user into the testing database if it doesn't exist and also update it if it already exists.

So now, with @sergiu17 suggestion I'm getting closer! It's now storing into the testing database if that user does not yet exist, but if it does exist am getting an integrity constraint violation due to the users table unique email.

So this is now working on first pass:

$user = \App\Models\User::find(1);
$user->first_name = 'Test';
$user->save();
$user->replicate()->setConnection('testing')->save();

But if running that code again I get the following error:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '[email protected]' for key 'users_email_unique'

I'm sure that by replicating the model it's creating a non-existing instance which then all attributes on the model are dirty, but in this case the user already exists within the testing database and I'm simply wanting to update that user.

Any suggestions how I can get around this?

Snapey's avatar
Snapey
Best Answer
Level 122

Its not the right solution. You should replicate outside of Laravel.

if thats not possible, then consider using eloquent model events to fire updates to your other database. You don't want this stuff littered through your code.

1 like
Scooby's avatar

@snapey Thank you very much! Your advice on using model events led me to a nice solution. Ended up using the following in my User model:

protected static function booted()
{
    static::saved(function ($user) {
        $user->setConnection('testing')->saveQuietly();
    });
}

I had to use saveQuietly() because using save() always fires the saved event and loops infinitely.

Resources:

https://laravel.com/docs/8.x/eloquent#events-using-closures

https://laravel.com/docs/8.x/eloquent#saving-a-single-model-without-events

Please or to participate in this conversation.