Asumiendo el Orden Modelo
class Order extends Model { use HasFactory; protected $table = 'order'; protected $primaryKey = 'id'; public $incrementing = false; protected $keyType = 'string'; protected $guarded = []; public function extra(){ return $this->hasOne(Extra::class); } public function products(){ return $this->hasMany(Product::class); } }y el Modelo Extra
class Extra extends Model { use HasFactory; protected $table = 'extra'; protected $guarded = []; public function order(){ $this->belongsTo(Order::class); } }y el producto modelo
class Product extends Model { use HasFactory; protected $table = 'product'; protected $guarded = []; public function order(){ return $this->belongsTo(Order::class); } }Ahora, desde una API recibo datos. Con estos datos, quiero alimentar los modelos y luego almacenar la información en la base de datos.
El enfoque que hay atm es:
foreach ($list as $item) { $order = new Order(); $order->id = $item['id']; $order->title = $item['title']; $order->save(); $extra = new Extra(); $extra->foo= $item['path']['to']['foo']; $extra->bar= $item['path']['to']['bar']; $order->extra()->save($extra) $order->products()->createMany($item['path']['to']['products']); }El problema es que este código guarda tres veces por cada bucle, uno por pedido, uno por extra, uno por producto. Me gustaría saber si hay otra forma que pueda usar para recopilar los datos dentro del for-each y fuera de él, para hacer algo como
Order::insert($array_of_data);Me imagino que se vería así, pruébalo y si no funciona, avísame y eliminaré la respuesta.
$orders = []; $extras = []; $products = []; foreach ($list as $item) { $orders[] = [ 'id' => $item['id'], 'title' => $item['title'], ]; $extras[] = [ 'foo' => $item['path']['to']['foo'], 'bar' => $item['path']['to']['bar'], ]; $products[] = [ 'order_id' => $item['id'], 'foo' => $item['path']['to']['products']['foo'] // or data it has ]; } Order::insert($orders); Extra::insert($extras); Product::insert($products); // make sure each product has order id and data which is not visible hereTambién sugiero considerar convertir $list en una colección y luego iterar sobre ella, si los datos son bastante grandes, puede usar LazyCollection, que es lo mismo que la colección pero mejor para procesar conjuntos de datos más grandes.
Aquí hay un ejemplo de cómo lo haría usando la colección perezosa
LazyCollection::make($list) ->each(function (array $item) { $order = Order::create( [ 'id' => $item['id'], 'title' => $item['title'] ], ); Extra::create( [ 'order_id' => $item['id'], 'foo' => $item['path']['to']['foo'], 'bar' => $item['path']['to']['bar'], ], ); $order->products()->createMany($item['path']['to']['products']); });Si bien no necesariamente crea muchos a la vez, es un salvador de memoria y se procesará con bastante rapidez.