LaravelでCSVデータをmysqlへ登録する処理を作成したので、その方法を説明します。
LaravelでMySQLに登録しているデータを取得するAPIがあり、自動テストを行う際に、テスト用データを作成したいのですが、テストメソッドの中でfactoryを使用してデータを作成すると、テストコードが冗長化して見づらくなってしまいます。
テストコードにはテストのロジックだけを書きたいため、テストデータの作成は外部ファイル(CSVファイル)に定義し、テスト実行時にデータを作成する処理を含めないようにするため、LaravelでCSVデータをmysqlへ登録するようにしました。
ロジックの内容
CSVファイルにテストで使用するDBのデータを作成して、それをテストコード実行するときにインポートしてテストデータを作成する。
CSVはテストケースごとにディレクトリを分けて、1つのテストケースで登録したいDBごとにcsvファイルを分けることにする。
csvファイル名はDB名と同じ名前にして、一致する名前のDBにcsvの内容を登録するものとする。
ディレクトリ構造
database
┗ seeders
┗ CsvToDataSeeder.php //csvファイルの中のCSVをすべてmysqlに登録する
tests
┗ csv
┗ testCase1
┗ 各CSVファイル(ファイル名はDB名と同じにする)
┗ Feature
┗ ***Test.php
実際のコード
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class CsvToDataSeeder extends Seeder
{
public function run(string $testCaseName): void
{
// テストケース名に一致するディレクトリ内の全てのCSVファイルを取得
$files = glob(base_path("tests/csv/{$testCaseName}/*.csv"));
foreach ($files as $file) {
// CSVファイルを読み込む
$csv_data = $this->csvToArray($file);
// ファイル名からテーブル名を取得(拡張子.csvを削除)
$tableName = basename($file, '.csv');
// データベースに挿入するためのデータの作成
$insert_data = [];
foreach ($csv_data as $row) {
// 'null'文字列をNULLに変換
foreach ($row as $key => $value) {
if ($value === 'null') {
$row[$key] = null;
}
}
$insert_data[] = $row;
}
// データベースに挿入
DB::table($tableName)->insert($insert_data);
}
}
protected function csvToArray($filename)
{
$rows = [];
if (($handle = fopen($filename, 'r')) !== false) {
$header = fgetcsv($handle, 0, ','); // ヘッダー行を読み込む
while (($row = fgetcsv($handle, 0, ',')) !== false) {
$rows[] = array_combine($header, $row);
}
fclose($handle);
}
return $rows;
}
}
runメソッド内容について
このクラスは、CSVファイルからデータを読み込み、それをデータベースに挿入します。
runメソッドは引数に「テストケース名」を受け取っています。
テストケース名に一致するディレクトリ内の全てのCSVファイルを取得し、それぞれのファイルに対してDBに登録する処理を行います。
各CSVファイルはcsvToArrayメソッドによって配列に変換され、その後、ファイル名からテーブル名のみを取得します(拡張子.csvを削除)。
次に、データベースに挿入するためのデータを作成します。
各行に対して、'null'文字列をNULLに変換し、それぞれの値を上書きします。
そして、その行を挿入データの配列に追加します。
最後に、DB::table($tableName)->insert($insert_data);を使用して、データをデータベースに挿入します。
csvToArrayメソッドの内容について
csvToArrayメソッドは、指定されたCSVファイルを開き、ヘッダー行を読み込みます。
その後、各行を読み込み、ヘッダーと行の値を組み合わせて配列を作成します。
これを繰り返し、全ての行を処理したら、ファイルを閉じて配列を返します。
// テストデータを作成
$seeder = new CsvToDataSeeder();
$seeder->run('testCase1');
自動テストのファイルの中で、runメソッドを実行します。
引数にテストケース名を渡すことで、CsvToDataSeeder.phpの中で同一名のディレクトリ内のcsvファイルをすべてDBに登録できます。