Пакетная вставка ActiveRecord (yii2)

Можно ли вставить несколько строк в один запрос с помощью Yii ActiveRecord? Или это возможно только через объекты DAO более низкого уровня?

У меня есть две модели: 1- транзакция 2-транзакцияItems

В элементах транзакций есть несколько строк (добавление строки по щелчку).

Я хочу хранить несколько строк транзакций в базе данных.

Скриншот таблицы элементов транзакции


person user1561346    schedule 08.12.2014    source источник


Ответы (1)


Вы можете использовать batchInsert() метод yii\db\Command. Подробнее см. здесь. При использовании его с ActiveRecord убедитесь, что все данные проверены перед вставкой.

Предполагая, что у вас есть массив $models с классом Post, это можно сделать так:

$rows = [];
foreach ($models as $model) {
    if (!$model->validate()) {
        // At least one model has invalid data

        break;
    }

    $rows[] = $model->attributes;
}

Если модели не требуют проверки, вы можете сократить приведенный выше код, используя ArrayHelper для построения массива $rows.

use yii\helpers\ArrayHelper;

$rows = ArrayHelper::getColumn($models, 'attributes');

Затем просто выполните пакетную вставку:

$postModel = new Post;

Yii::$app->db->createCommand()->batchInsert(Post::tableName(), $postModel->attributes(), $rows)->execute();

P.S. $postModel только что использованный для извлечения списка имен атрибутов, вы также можете извлечь его из любой существующей $model в вашем массиве $models.

Если вам не нужно вставлять все атрибуты, вы можете указать это при заполнении массива $rows:

$rows[] = [
    'title' => $model->title,
    'content' => $model->content,
];

Не забудьте заменить $postModel->attributes на ['title', 'content'].

В случае большего количества атрибутов вы можете использовать некоторые функции массива, чтобы указать точные атрибуты для вставки.

person arogachev    schedule 08.12.2014
comment
Итак, ответ - нет? Я должен использовать DAO. - person user1561346; 08.12.2014
comment
Я думаю, что в настоящее время ActiveRecord не поддерживает это из коробки. Вы можете провести дополнительное исследование, но я не могу его найти. - person arogachev; 08.12.2014
comment
$postModel-›атрибуты должны быть $postModel-›attributes() - person Dodo; 30.05.2015
comment
@Dodo Спасибо за замечание, исправил ответ. - person arogachev; 30.05.2015
comment
@arogachev: как получить все идентификаторы последней вставки в пакетной вставке? - person Santosh; 16.11.2015
comment
Расширенную версию этого подхода (с поддержкой событий beforeSave и afterSave) можно найти здесь: stackoverflow.com/a/39601194/3793592 - person IStranger; 21.09.2016
comment
работает хорошо; вы должны учитывать, что это дает ошибку sql, если массив данных оказывается пустым - person zuups; 03.04.2018
comment
пользовательский behaviors() на этой модели Post все еще работает? В моем случае это не так. - person Morilla Thaisa; 21.09.2018
comment
что, если я хочу пропустить любой столбец из $rows? - person Moeez; 07.01.2020