I have two Model classes with a oneToMany relation like this
App\Carclass Car extends Model
{
public $timestamps = true;
protected $fillable = [
'name',
'price'
];
public function parts ()
{
return $this->hasMany('App\Part');
}
}
App\Part
class Part extends Model
{
public $timestamps = false;
protected $fillable = [
'name',
'price'
];
public function car ()
{
return $this->belongsTo('App\Car');
}
}
The client makes a POST request with a JSON representing a Car with a nested Array of Parts
{
"name": "Fiat Punto",
"price": 15000,
"parts": [
{
"name": "wheel",
"price": 300
},
{
"name": "engine",
"price": 5000
}
]
}
Is there a way to save the Car model and create the relations in just one hit?
I tried to do this in my controller but it doesn't work:
...
public function store (Request $request) {
$input = $request->all();
Car::create($input);
}
...
PS: I already know how to do the task with a foreach
or array_reduce
, just wondering if laravel could do that for me
Here is how i implemented the controller right now:
...
public function store (Request $request) {
$input = $request->all();
$car = Car::create($input);
$parts = array_reduce(
$input['parts'],
function ($carry, $item) {
array_push($carry, new Part($item));
return $carry;
},
[]
);
$car->parts()->saveMany($parts);
}
...
Any improvement is welcome
I don´t think there is a way of getting around the fact that you need to create each of the App\Part model instances that are defined in the request object. So, at some point you have to iterate over those items in the request object, meaning you have (at least) two options. Those are both described here.
On a side note I think in this case it is better to use a foreach loop for the first option:
foreach ($request->input('parts') as $item) {
$car->parts()->save(new Part($item));
}
If you'd go for the second option of storing them in an array first, then I think array_map is the more appropriate method to use (because there is no actual "reducing" going on):
$parts = array_map(function($part) {
return new App\Part($part);
}, $request->input('parts'));
$car->parts()-saveMany($parts);
Edit: As per suggestion from @TomasKim, with only 2 queries - one for the Car-model and another for the Part-models:
$parts = array_map(function($part) {
return [...$part, 'car_id' => $car->id];
}, $input['parts'])
DB::table('parts')->insert($parts);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With