Hello there!
I've been searching on how to create a model with a relationship and save both of them if everything is right.
This is my code that handles the store request right now:
<?php
namespace App\Http\Requests;
use Illuminate\Support\Facades\Request;
use Illuminate\Foundation\Http\FormRequest;
use Carbon\Carbon;
use App\User;
use App\Room;
use App\Utilities\RandomGenerators;
class RoomsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'description' => 'required|max:50',
'programmedAt' => 'nullable|date',
'room_admin' => 'required',
];
}
/**
* Persist the request into database.
*
*/
public function persist()
{
$slug = null;
$existsRoom = null;
do {
$slug = RandomGenerators::randomInteger(8);
$existsRoom = Room::where('slug', $slug)->first();
} while($existsRoom !== null);
$this->merge([
'slug' => $slug,
]);
$user = User::findOrFail($this->input('room_admin'));
$room = Room::create(
$this->all()
)->administrator()->associate($user);
if ($this->input('programmed_at') != null) {
// Some date validations stuff...
$room->status = Room::PROGRAMMED;
} else {
$room->status = Room::CREATED;
}
$room->save();
return $room->fresh();
}
}
Here I have some problems:
-
First of all, if something wrong happens with date validations or any error is thrown after the ::create(...) function, the room is created without user relationship and It conflicts with my views, which shows user information when accessing to the room details.
-
Secondly, I have to create the room before assigning a status depending if it is programmed or not, then associate the user. The problem is that I have to call the save() function to apply changes, which will create another database query and call the update function. This is also "bad", because when the save() function is called the update_at column is changed too and should be the same value as the create_at function, because we are at the creation point and not updating.
My goals:
- Use transactions or wathever I should use to complete this task as a "block". If something wrong happens, revert and DO NOT insert ANY data to the database.
I've been looking an answer in this post https://laravel.io/forum/06-11-2014-how-to-save-eloquent-model-with-relations-in-one-go made by evandertino, who suggests using transactions, but seems not fitting my goals.
Any suggestion here of how can I rebuild the persist() function to store the room, with extra data stored by the APP and the relationship all in one block, to revert changes if something wrong happens?
Thanks everyone for your time and I hope its clear enough. If you need any further information, let me know and I will answer ASAP.
Best regards,
Diego.