【问题标题】:Save model outside of for-each loop在 for-each 循环之外保存模型
【发布时间】:2021-09-30 02:53:00
【问题描述】:

假设 模型顺序

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 次,1 次用于订购,1 次用于额外,1 次用于产品。 我想知道是否可以使用另一种方法来收集 for-each 内部和外部的数据,以制作类似

Order::insert($array_of_data);

【问题讨论】:

  • 是的,只需将要插入的数组保存到数组中,而不是将属性分配给模型并保存
  • @lagbox 感谢您的回答。有没有可能给我看一些代码来理解?此外,关系(一对一,一对多)呢?幕后的东西会照顾他们吗?
  • 不,没有什么可以处理这样的事情,insert 无论如何都绕过了 eloquent ...您目前所做的已经足够了,因为您需要保存的记录及其关系 ID
  • 如果可能的话,添加几行代码!谢谢

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


【解决方案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']);
    });

虽然它不一定一次创建多个,但它是内存的救星,并且会很快处理

【讨论】:

    猜你喜欢
    • 2015-11-12
    • 1970-01-01
    • 2010-09-20
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多