PHPフレームワークLaravel入門を学習中にデータベースにアクセスできない問題が発生しました。
エラーメッセージは『Database does not exist.(SQL:PRAGMA foreign_keys = ON;)』との表示。
.envファイルのDB_DATABASE=database.sqliteをコメントアウトすることで解決したのですが、この記事では詳しい原因と対処法をお伝えします。
エラーメッセージの意味
『Database does not exist.(SQL:PRAGMA foreign_keys = ON;)』
こちらのメッセージ、意味は「データベースが存在しません。」です。
本では誤植があったようで、実際にはデータベースファイル(database.sqlite)のパスを指定する必要がありましたが、DB_DATABASE=database.sqLiteと入力していたため、「データベースが存在しない」というエラーが発生したようです。
さらなる問題と対処法
誤植に気付き、ファイルパスを絶対パスで記入したところ、The environment file is invalid!のエラー。
詳細はFailed to parse dotenv file due to unexpected whitespace.(予期しない空白のため、dotenvファイルの解析に失敗しました。)とのこと。
おそらくファイルパスに日本語が含まれていたため、うまくいかなかったのでしょう。
相対パスでの表記もうまくいかず、対処法を探したところ.envファイルのDB_DATABASE=〜をコメントアウトすることでうまくいくとのこと。
# 前略
DB_DATABASE=〜
# 後略
# 前略
# DB_DATABASE=〜
# 後略
【参考】laravelにてdatabase.sqliteが存在しない(does not exist)と表示される|teratail
実際に書き換えて、サーバーを立ち上げ直したところ、きちんと動作しました。
対処法解説
では、なぜDB_DATABASE=〜をコメントアウトすることで、きちんと動作するようになったのでしょうか?
Laravelではデータベースを指定する際にconfig/database.phpから設定を読み込みます。
このdatabase.phpではデータベースの指定に以下のようなコードが書かれています。
# 前略
'database' => env('DB_DATABASE', database_path('database.sqlite')),
# 後略
まず、env()から見ていきましょう。
グローバルヘルパー関数 env()
ここで使われているenv()はLaravelに用意されているグローバルヘルパー関数の1つで、環境変数の値を取得します。
取得できない場合はデフォルト値を返します。
$env = env('APP_ENV');
// APP_ENVがセットされていない場合、第二引数がデフォルト値('production')として返る
$env = env('APP_ENV', 'production');
database.phpに書かれているenv('DB_DATABASE', database_path('database.sqlite'))は、「環境変数DB_DATABASEに保存されている値を取得する!なければdatabase_path('database.sqlite')の値を使う!」ということだったんですね。
では、DB_DATABASEをコメントアウトすることで、取得するようになる第二引数database_path('database.sqlite')はどういう関数なのでしょうか?
グローバルヘルパー関数 database_path()
database_path()もグローバルヘルパー関数のひとつです。
database/ディレクトリの完全パスを返します。
database/ディレクトリ内の指定ファイルへの完全パスを生成することもできます。
$path = database_path();
// databaseディレクトリ内のfactories/UserFactory.phpへの完全パスを生成
$path = database_path('factories/UserFactory.php');
env('DB_DATABASE', database_path('database.sqlite'))で使われていたdatabase_path('database.sqlite')は「database/ディレクトリのdatabase.sqliteの完全パスを取得する!」ということだったんですね。
【参考】ヘルパ 5.5 Laravel( database_path() )
2つの関数をまとめると
それぞれの関数でやっていることがわかったので、database.phpに書かれている
# 前略
'database' => env('DB_DATABASE', database_path('database.sqlite')),
# 後略
が何をしているかをまとめると、
「環境変数DB_DATABASEに保存されている値を取得する!なければdatabase/ディレクトリのdatabase.sqliteの完全パスを取得する!」
ということになります。
対処法として行った「.envファイルのDB_DATABASE=database.sqliteをコメントアウトする」というのは、database_path()で取得した完全パスをデータベースとして指定するようにするということだったんですね!
その他の対処法
そうなると、「.envファイルのDB_DATABASE=database.sqliteをコメントアウトする」以外にも対処法が見えてきますね!
.envファイルのDB_DATABASE=database.sqliteをコメントアウトせずに
# 前略
'database' => env('DB_DATABASE', database_path('database.sqlite')),
# 後略
を
# 前略
'database' => database_path('database.sqlite'),
# 後略
のように変更して、環境変数の読み込みをなくして直接database.sqliteの完全パスを指定してもきちんと動作するようになりました。
まとめ
Laravelで『Database does not exist.』のエラーが出た際は、データベースのパスの指定が間違っている可能性があるので、
-
.envファイルのDB_DATABASE=database.sqliteをコメントアウト
# 前略
# DB_DATABASE=〜
# 後略
もしくは
- 環境変数の読み込みをなくして直接
database.sqliteの完全パスを指定
# 前略
'database' => database_path('database.sqlite'),
# 後略
を試してみましょう!
