在 for-each 循环之外保存模型

时间:2021-07-22 20:52:41

标签: php laravel laravel-5 eloquent laravel-8

假设模型顺序

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);
    }
}

Model Extra

class Extra extends Model {

    use HasFactory;
    protected $table = 'extra';
    protected $guarded = [];

    public function order(){
        $this->belongsTo(Order::class);
    }
}

模型产品

class Product extends Model {
    use HasFactory;
    protected $table = 'product';
    protected $guarded = [];
    public function order(){
        return $this->belongsTo(Order::class);
    }
}

现在,我从 API 接收数据。有了这些数据,我想提供模型,然后将信息存储到数据库中。

atm 的方法是:

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']);
}

问题是这段代码每次循环保存3次,一次用于订单,一次用于额外,一次用于产品。 我想知道是否有另一种方法可以用来收集 for-each 内部和外部的数据,以制作类似

Order::insert($array_of_data);

1 个答案:

答案 0 :(得分:1)

我想它看起来像这样,尝试一下,如果不起作用请告诉我我会删除答案

$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 here

我还建议考虑将 $list 转换为集合,然后对其进行迭代,如果数据很大,您可以使用 LazyCollection,它与集合相同,但更适合处理更大的数据集

这里有一个例子,你将如何使用惰性集合来做到这一点

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']);
    });

虽然它不一定一次创建多个,但它是内存救星并且处理速度非常快