【问题标题】:Laravel - multi-table insert with relationshipsLaravel - 具有关系的多表插入
【发布时间】:2018-10-09 20:46:32
【问题描述】:

我有 3 个表格需要在创建订单时填充,我想知道执行此操作的最佳方法。

表格

Orders
- id (pk)
- company_id
- address_id (join to items table)
- date
- source
- ...

Addresses
- id (pk)
- company_id
- name
- email
- address
- ...

Items
- id (pk)
- order_id (join to orders table)
- product_id
- qty
- ...

关系

  • 地址表属于订单表
  • 订单有很多商品
  • 我们有一个多租户(单数据库)结构,因此 company_id 用于分隔公司之间的数据。订单和地址都属于公司。

创作

我的理解是,需要先创建地址才能获取 ID。然后将创建订单,然后是商品。

我还想确保如果任何插入失败,则不会保存任何数据(就像在 SQL 事务中一样)。

我想知道是否有人可以为我指明正确的方向以找到最好的方法?到目前为止,我有以下内容

$address = OrderAddress::create([
    'company_id' => Auth::user()->company_id,
    'name' => 'test test',
    'email' => 'test@test.com',
    'address' => '78 test street',
]);
$order = $address->order()->create([
    //'address_id' => populated by model
    'company_id' => Auth::user()->company_id,
    'date' => '2018-03-23',
    'source' => 'mystore'
]);
foreach($items as $item){
    OrderItem::create([
        'order_id' => $order->order_id,
        'product_id' => $item->product_id,
        'qty' => $item->qty
    ]);
}

我的主要问题是:

  1. 这不能用作事务,即失败不会创建回滚。
  2. 我不确定我是否充分发挥了模型关系的潜力。

【问题讨论】:

  • 一个事务绝对应该有效。你是怎么用的?

标签: php laravel eloquent


【解决方案1】:

DB::transaction(...)

DB::beginTransaction();

您可以通过rollBack方法回滚事务:

DB::rollBack();

最后,您可以通过 commit 方法提交事务:

DB::commit();

【讨论】:

    【解决方案2】:

    基本上您可以进行两项改进。每个问题一个。

    1. 要将所有内容包装在事务中,您可以将 create 语句放在 DB::transaction(...) 块中。作为参考,请查看the manual。还有另一种使用其中描述的事务的方式。

    2. 您在创建Order 时使用的相同关系create 方法也可以应用于OrderItems$order->items()->create([...])

    最终的代码 sn-p 可能如下所示:

    DB::transaction(function () {
        $address = OrderAddress::create([
            'company_id' => Auth::user()->company_id,
            'name' => 'test test',
            'email' => 'test@test.com',
            'address' => '78 test street',
        ]);
        $order = $address->order()->create([
            'company_id' => Auth::user()->company_id, // actually, this information is already available through the `address`
            'date' => '2018-03-23',
            'source' => 'mystore'
        ]);
        foreach($items as $item){
            $order->items()->create([
                'order_id' => $order->order_id,
                'product_id' => $item->product_id,
                'qty' => $item->qty
            ]);
        }
    });
    

    如果是orderItems()而不是items(),请务必更改关系名称。

    【讨论】:

    • 感谢@Namoshek。我可以扩展我的问题并询问您建议将此类代码存储在哪里吗?我读到保持控制器瘦而模型胖是一种很好的做法,但考虑到这段代码跨多个控制器运行,这仍然有意义吗?
    猜你喜欢
    • 2020-08-30
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2013-11-11
    • 2021-09-07
    相关资源
    最近更新 更多