yii2 使用 ActiveRecord 批量插入 [英] yii2 batch insert with ActiveRecord

查看:25
本文介绍了yii2 使用 ActiveRecord 批量插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 yii2 ActiveRecord 在我的表中插入多条记录.我已经知道我可以使用这段代码了

I want to insert multiple record in my table using yii2 ActiveRecord. I already know that I can use this code

$connection->createCommand()->batchInsert('user', ['name', 'age'], [
    ['Tom', 30],
    ['Jane', 20],
    ['Linda', 25],
])->execute();

但是通过这种方法,我的模型验证没有执行.我已经读过这个问题ActiveRecord 批量插入 (yii2)

but by this approach my model validations are not executing. and I already have read this question ActiveRecord batch insert (yii2)

但也通过一种棘手的方式进行验证,考虑我想使用 ActiveRecords 事件填充 created_atupdated_at 列.

but also by doing validation in a tricky way, consider I want to fill created_at and updated_at columns using ActiveRecords events.

就这样

public function beforeSave($insert)
{
    if (parent::beforeSave($insert)) {
        if($insert)
            $this->created_at = date('Y-m-d H:i:s');
        $this->updated_at = date('Y-m-d H:i:s');
        return true;
    } else {
        return false;
    }
}

推荐答案

我认为使用 beforeSave 事件(和类似的东西)并不是一个好主意,因为它会为 each 模型触发.但是,您希望一次保存多个模型.我建议使用批量方法.

I think is not good idea to use beforeSave events (and similar stuff) because it will trigger for each model. However you want save multiple models at once. I recommend to use bulk methods.

在类似的情况下,我通常使用以下批量"方法(代码未经测试,仅举例):

In similar cases I use usually following "bulk" approach (code not tested, just for example):

namespace commoncomponents;

class Model extends yiiaseModel {

    /**
     * Saves multiple models.
     *
     * @param ActiveRecord[] $models
     * @return bool
     */
    public static saveMultiple($models){

        if(count($models) > 0){

            $firstModel      = reset($models);
            $columnsToInsert = $firstModel->attributes();   // here you can remove excess columns. for example PK column.
            $modelsToInsert  = [];
            $rowsToInsert    = [];

            foreach($models as $model){
                if ($this->beforeSave(true)) {
                    $modelsToInsert[] = $model;
                }
            }

            foreach($modelsToInsert as $model){
                $rowsToInsert[] = array_values($model->attributes);     // here you can remove excess values
            }

            $numberAffectedRows = Yii::$app->db->createCommand()
                ->batchInsert($firstModel->tableName(), $columnsToInsert, $rowsToInsert)
                ->execute();

            $isSuccess = ($numberAffectedRows === count($models));

            if($isSuccess){
                $changedAttributes = array_fill_keys($columnsToInsert, null); 

                foreach($modelsToInsert as $model){
                    $model->afterSave(true, $changedAttributes);
                }
            }

            return $isSuccess;

        } else {

            return true;
        }

    }

}

这个类可以用:

use commoncomponentsModel;

/**
 * @var SomeActiveRecord[] $models Array that contains array of active records (type SomeActiveRecord)
 */ 

// ...

if (Model::validateMultiple($models)){

    if(!Model::saveMultiple($models)){
        // ... some error handling
    }

} else {

    foreach($models as $model){
        if($model->hasErrors()){

            $errors = $model->getFirtsErrors();
            // ... some error handling

        }
    }

}

此外,为了更方便地使用多个模型,可以开发实现 ArrayAccessIterator 接口的特殊 Collection 类.该集合可以作为简单数组进行迭代,但它包含用于批量操作的特殊方法.像这样的:

Additionally, for more convenient working with multiple models can be developed special Collection class that implements ArrayAccess and Iterator interfaces. This collection can iterated as simple array, however it contains special methods for bulk operations. Something like this:

foreach($modelCollection as $model){
    // ...
}

$modelCollection->validate();   // works similar to commoncomponentsModel::validateMultiple()
$modelCollection->save();       // works similar to commoncomponentsModel::saveMultiple()

这篇关于yii2 使用 ActiveRecord 批量插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆