◀ 4.

Changing columns for table "~" requires Doctrine DBAL; insta

▶
この記事の要点
  • Laravel のマイグレーションで ->change() によるカラム定義変更を実行したときに出るエラー
  • 原因: Laravel 10 以前はカラム変更に doctrine/dbal パッケージが必要なのに、インストールされていない
  • 対処: プロジェクトのルートで composer require doctrine/dbal を実行し、再度 php artisan migrate
  • Laravel 11 以降は DBAL 不要(ネイティブ実装)。代わりに「残したい修飾子を全部書き直す」必要がある
  • 本番では composer.json に追加してデプロイする。サーバー上で直接 require しない

エラー内容

Changing columns for table "~" requires Doctrine DBAL; install "doctrine/dbal".

「~」の部分には変更しようとしたテーブル名が入ります。php artisan migrate の実行中に RuntimeException として表示され、該当マイグレーションは適用されずに止まります。

発生条件と原因

既存カラムの型・長さ・NULL 許可などを変える、次のようなマイグレーションを実行したときに発生します。

Schema::table('users', function (Blueprint $table) {
    $table->string('name', 100)->nullable()->change();
});

Laravel 10 以前のスキーマビルダーは、カラムの変更(change())を自前の SQL ではなく Doctrine DBAL というライブラリに任せていました。DBAL が現在のテーブル定義を読み取り、変更後との差分から ALTER TABLE 文を組み立てる仕組みです。ところが doctrine/dbal は Laravel 本体の必須依存ではなく任意インストールだったため、入れ忘れていると「カラム変更には Doctrine DBAL が必要です」というこのエラーになります。

Laravel のバージョンカラム変更(change)の扱い
8 / 9doctrine/dbal が必須
10原則 doctrine/dbal が必要。Schema::useNativeSchemaOperationsIfPossible() を呼ぶとネイティブ実装を使える
11 以降doctrine/dbal 不要。Laravel 自身が ALTER 文を生成する

新しいカラムの追加($table->string('x') だけ)や、テーブル作成ではこのエラーは出ません。既存カラムを変更する操作に限って発生します。

対処法(Laravel 10 以前)

  1. プロジェクトのルートディレクトリ(composer.json がある場所)に移動する
  2. 以下のコマンドで doctrine/dbal を導入する
    composer require doctrine/dbal
  3. もう一度マイグレーションを実行する
    php artisan migrate

Composer は Laravel のバージョンと互換性のある DBAL のバージョンを自動で選びます。Laravel 7 以前の古いプロジェクトでは DBAL 3 系と組み合わせると別のエラー(PDOMySql\Driver が見つからない等)になることがあるため、その場合は composer require doctrine/dbal:^2.13 のようにメジャーバージョンを指定します。

Laravel 11 以降にアップグレードした場合の注意

Laravel 11 以降では DBAL を使わずにカラム変更ができるようになりました。一方で挙動が変わり、change() を使うときは変更後も残したい属性をすべて書く必要があります。書かなかった修飾子(nullable・default・comment など)は外れてしまいます。

// 変更前: votes は unsigned・default(1)・comment 付き
// Laravel 11 以降で nullable を追加したい場合は、残す属性も全部書く
$table->integer('votes')
    ->unsigned()
    ->default(1)
    ->comment('得票数')
    ->nullable()
    ->change();

アップグレード時、もう使わない doctrine/dbal は composer remove doctrine/dbal で外せます(ほかのパッケージが依存していないか確認してから)。

落とし穴

  • 本番サーバーで直接 composer require しない: ローカルで追加して composer.json と composer.lock をコミットし、本番では composer install で入れる
  • require-dev に入れて本番で失敗: 本番でもマイグレーションを流すなら通常の require に入れる(--no-dev で install すると dev 依存は入らない)
  • enum 型を含むテーブル: DBAL 2 系では enum カラムがあるテーブルの変更で「Unknown database type enum requested」が出ることがある。DBAL の型マッピング設定を追加するか、ALTER 文を DB::statement() で直接書く
  • 途中まで適用されたマイグレーション: MySQL は DDL がトランザクションに含まれないため、1 ファイル内の前半だけ適用済みになっていないか確認してから再実行する

確認方法

# doctrine/dbal が入っているか、バージョンは何か
composer show doctrine/dbal

# Laravel のバージョン
php artisan --version

# マイグレーションの適用状況
php artisan migrate:status

マイグレーション成功後は、DB 側で SHOW CREATE TABLE テーブル名; を実行し、型・NULL 許可・デフォルト値が意図通りに変わっているか確認しましょう。

関連

子ページ

子ページはありません

同階層のページ
  1. SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost'
  2. Add [~] to fillable property to allow mass assignment on [App\~].
  3. PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' in ~
  4. Changing columns for table "~" requires Doctrine DBAL; install "doctrine/dbal"
  5. MethodNotAllowedHttpException No message
  6. Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
  7. production.ERROR: No application encryption key has been specified.
  8. Dotenv values containing spaces must be surrounded by quotes.
  9. Laravel \ Socialite \ Two \ InvalidStateException
  10. The page has expired due to inactivity. Please refresh and try again.
  11. Failed to clone https://github.com/symfony/thanks.git via https, ssh protocol
  12. Illegal offset type
  13. Cannot access protected property Illuminate\Http\Request::$...
  14. Emitted value instead of an instance of Error
  15. 画像保存時にInternal Server Error
  16. Failed to authenticate on SMTP server with username ...
  17. PostTooLargeException
  18. Database hosts array is empty.
  19. Invalid request (Unsupported SSL request)
  20. does not comply with psr-4 autoloading standard. Skipping.
  21. MySQLのSTR_TO_DATE関数を使用するとnullが返却される問題