Laravel - многостоловая вставка со связями - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть 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 используется для разделения данных между компаниями. Заказ и адрес принадлежат компании.

Создание

Насколько я понимаю, сначала необходимо создать адрес, чтобы получить идентификатор. Затем будет создан заказ, за ​​которым следуют элементы.

Я также хотел бы убедиться, что в случае неудачной вставки никакие данные не будут сохранены (как в транзакции 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. Я не уверен, что я использую отношения модели в полной мере.

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

DB :: транзакция (...)

или

DB :: BeginTransaction ();

Откат транзакции можно выполнить с помощью метода rollBack:

DB :: RollBack ();

Наконец, вы можете зафиксировать транзакцию с помощью метода commit:

DB :: совершить ();

0 голосов
/ 29 апреля 2018

Есть два основных улучшения, которые вы можете сделать. По одному на каждый из ваших вопросов.

  1. Чтобы обернуть все в транзакции, вы можете поместить операторы create в блок DB::transaction(...). Для справки, посмотрите руководство . Существует также другой способ использования транзакций, описанных здесь.

  2. Тот же метод отношений create, который вы использовали при создании Order, также может применяться к OrderItems: $order->items()->create([...]).

Окончательный фрагмент кода может выглядеть примерно так:

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().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...