バルクインサート・・・複数レコードのインサートを一括で行う。速い。
ORMパッケージの使用が前提です。
通常のクエリビルダでバルクインサート
\DB::insert('tablename')
->columns([
'column1',
'column2',
'column3',
])
->values([1,2,3])
->values([1,2,3])
->values([1,2,3])
...
->execute();
クラスメソッド化
public static function insert_multi($table, array $columns, array $datum);
これでも十分だけど
- 毎回カラム名を指定する必要がある
- データの並びをカラム名の並びに合わせる必要がある
このあたりをもう少し楽にしたい。
ORMにメソッドを生やす。
base.php
class Model_Base extends \Orm\Model
{
public static function insert_multi($datum)
{
$table = static::table();
$columns = array_keys(static::properties());
$query = \DB::insert($table)
->columns($columns);
foreach ($datum as $data) {
$values = [];
($data instanceof \Orm\Model) and ($data = $data->to_array());
foreach ($columns as $col) {
$values[] = (isset($data[$col])) ? $data[$col] : null;
}
$query->values($values);
}
return $query->execute();
}
}
//想定している引数
[
['name' => 'fuel', 'comment' => 'php'],
['name' => 'orm', 'comment' => 'model'],
...
];
//もしくは
[Model, Model, Model...]
//extends
Model_Blog::insert_multi($blogs);
Model_Post::insert_multi($posts);
Model_Image::insert_multi($images);
ORMモデル自身でテーブル名とカラム名を解決するので
挿入したいデータを渡すだけでOK。
(ORMが主役みたいに書いてるけど、実質テーブル情報の書かれた設定ファイル扱い)
クラス名を引数に取れば、別クラスに切り出すパターンでも
・・・びみょう?
class Helper
{
public static function insert_multi($classname, array $datum);
}
Helper::insert_multi(Model_User::class, $users);
おまけ Laravelのdestroy的なの
※複合主キー未対応
public static function destroy($id)
{
$primary_key = static::primary_key()[0];
return static::query()->where($primary_key, 'in', (array)$id)->delete();
}
Model::destroy(1); //id 1を削除
Model::destroy([2,3,4]); //id 2,3,4を削除
参考にさせていただいた記事です。
FuelPHPのDatabase_Query_Builder_Insertでバルクインサートが使用できた話