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
@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')));
I have a package that does this, but it was more designed for AngularJS objects. It basically takes and array and saves it.
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.
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:-
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();
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.
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community