Support the ongoing development of Laravel.io →
Database Eloquent
Last updated 2 years ago.
0

Transactions may be what you need:
See the Laravel documentation about transactions here: Database Transactions
Here is an example on SO: Laravel Eloquent ORM Transactions

Last updated 2 years ago.
0

@Ilyes512 this has nothing to do with transactions

You have to find the ship first to which you want to save the captain in

This is to ensure that when you save the captain, the records of the ship found are also saved with it. e.g) ship_id in the captains table

So doing something like this, should work

$ship->find(1)->captain()->save(new Captain(array('name' => 'jean Luc Picard')));
Last updated 2 years ago.
0

I have a package that does this, but it was more designed for AngularJS objects. It basically takes and array and saves it.

http://github.com/lakedawson/vocal

Last updated 2 years ago.
0

@evandertino

What you say kinda makes sense. But suppose you have to create the ship at the same time with captain. In your case you save a ship first then you save the captain with a ship model.

However if ship is saved without problem but something goes wrong while saving captain. We will have a ship without a captain. I want to prevent this.

Last updated 2 years ago.
0

Oh yeah, now i get it...for that case now @Ilyes512 is right, you need transactions. So that when something goes wrong saving the captain everything is automatically rolled back.

But again, it cannot be possible at any given time for both records to be saved at the same time, the ship has to be saved first before the captain. It makes sense because, even in real life, a ship has to exist before the captain pops into it.

So something like this, is what i am thinking. I have not tested it but i think it should work

$ship = new Ship;
$ship->name = 'Enterprise';
$ship->registry = 'ncc-1701D';

$captain = new Captain;
$captain->name = 'jean Luc Picard';

DB::transaction(function() use ($ship, $captain) {
   $ship = $ship->save(); //Ship Exists First
   Ship::find($ship->id)->captain()->save($captain);//Captain is saved to existing ship
});

This way you will be guaranteed in both ways while saving, for instance in the above code:-

  • If something goes wrong when saving the ship, No ship will be saved and therefore no captain will be saved
  • If something goes wrong when saving the captain, The ship will be saved and No captain will be saved

To get more control when using these transactions, try{}catch{} blocks should do like this

DB::beginTransaction(); //Start transaction!

try{
   //saving logic here
   $ship = $ship->save();
   Ship::find($ship->id)->captain()->save($captain);
}
catch(\Exception $e)
{
  //failed logic here
   DB::rollback();
   throw $e;
}

DB::commit();
Last updated 2 years ago.
0

The original problem unfortunately isn't really solvable. Even if you can save all at once, if the first save fails, it fails. You CAN, however - use transactions to get around this, as was originally provided. Transaction statements will let you know if something is wrong with any of the queries, before you execute them. Just wrap it in a transaction block:

DB::transaction(function() {
    // do stuff
});

If any statement fails, it'll rollback any queries. So what you can do, is basically step through the queries you need to do and resolve it.

That all said and done, I'm currently working on a pull request that will allow for batch saves for related models.

Last updated 2 years ago.
0

Sign in to participate in this thread!

Eventy

Your banner here too?

defiant defiant Joined 27 May 2014

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.