Edited at

【Laravel】PHPUnitテスト用にSQLiteをDBに設定した際に気を付けるべきマイグレーションの記述と解決方法


つらい思いをした

テストコードが破城しているプロジェクトのシステム(Laravel5.6)に対して、とりあえず正常にテストが走るようにリファクタしようと思い、

まずはテストのDBをSQLiteに設定して個々のテストコードを直そうと思った矢先、マイグレーションの書き方が不味かったらしく、

SQLiteの仕様でこけました

のでとりあえずマイグレーションの記述をSQLiteでも対応できるように直しました。


SQLiteは1回の変更でdropColumnrenameColumnを複数回呼び出すことはできない

どうやらSQLiteは1回の変更でdropColumnrenameColumnを複数回呼び出すことはできないらしい

ので以下のようにマイグレーションを記述していると、MySQLでは正常に処理されるがSQLiteではエラーが発生する

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class DeleteNameAndKanaOnUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->dropColumn('name');
$table->dropColumn('kana');
});
}

/**
* Reverse the migrations.
*
* @return void
*/

public function down()
{
Schema::table('user', function (Blueprint $table) {
$table->string('name');
$table->string('kana');
});
}
}

以下エラー内容

BadMethodCallException: SQLite doesn't support multiple calls to dropColumn / renameColumn in a single modification.

なので複数の処理は以下のように修正する必要があります。

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class DeleteNameAndKanaOnUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->dropColumn('name');
});
Schema::table('user', function (Blueprint $table) {
$table->dropColumn('kana');
});
}

/**
* Reverse the migrations.
*
* @return void
*/

public function down()
{
Schema::table('user', function (Blueprint $table) {
$table->string('name');
});
Schema::table('user', function (Blueprint $table) {
$table->string('kana');
});
}
}


テーブル作成時はNOT NULL制約を指定できるが、列追加する際はNOT NULL制約をつけることができない

テーブルを作成するときはNOT NULL制約をつけることはできるみたいですが、後で列を追加するときにNOT NULL制約をつけることはできないみたいです。

なので以下のように書いている場合、エラーが発生します。

    /**

* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->string('hoge');
});
Schema::table('user', function (Blueprint $table) {
$table->string('huga');
});
}

以下エラー内容

PDOException: SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL

もしNOT NULL制約でない場合は以下のようにデフォルトでNULLを入れてやれば大丈夫のようです

    /**

* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->string('hoge')->nullable();
});
Schema::table('user', function (Blueprint $table) {
$table->string('huga')->nullable();
});
}

もしNOT NULL制約があるカラムの場合は以下のように一旦NULLを許可して、後でNOT NULL制約にする必要があるみたいです

(もっと他にやり方がありそうな気もしますが・・・)

    /**

* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::table('user', function (Blueprint $table) {
$table->string('tell')->nullable();
});
Schema::table('user', function (Blueprint $table) {
$table->string('tell')->nullable(false)->change();
});
}


おわり


  • そもそもテストDBにSQLiteを設定するのがいいのかわからない・・・


参考URL