11
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

【初心者向け】Laravelのデータベース設定でつまずいた話

はじめに

MAMPを使用してLaravelの環境を構築しようとした際にDB接続の設定でつまずいたため、その内容と解決した方法をまとめます。  

対象読者

初めてLaravelでwebアプリを作ろうとしている初心者の方。

LaravelのDB設定がうまくいかない方。 

開発環境

・mac book pro(Mojave) 
・MAMP(version5.7)
・MySQL
・Composer(version1.9.1)
・Laravel(ver5.8.3)

エラーにハマった経緯

もともとXAMPPを使用してLaravelのアプリを開発していました。
しかし、macで開発をする場合はMAMPを使用した方がベターであるとの話を聞いて、 これを機にMAMPを使おうと思いXAMPPの環境からMAMPの環境にアプリを移行しようとしたのですが、SQLSTATE[HY000] [2002] No such file or directoryのエラーが出てDBに接続できなくなりました。

移行する際にやったこと(失敗例)

XAMPPで環境を作った際、筆者はWEBサーバーもDBサーバーもよくわかっていませんでした。
調べたところ.envと/config/database.phpあたりがどうやらDB接続の設定ファイルらしいとわかり、見よう見まねで何とか接続することができました。

で、MAMPに移行するに当たって、久々にDB接続の設定ファイルを見た所、とりあえず、.envと/config/database.phpのそれらしいところをMAMPに合わせて修正すれば良さそうな気がしたのでやってみました。

MAMPのアプリを立ち上げてサーバーを起動させるとスタートページに飛ぶのでページ内にあるMySQLの設定を参照します。
スクリーンショット 2020-03-13 23.48.34.png

DB_HOST=localhost
DB_PORT=8889
DB_DATABASE=database_name
DB_USERNAME=root
DB_PASSWORD=root

/config/database.phpの中身は先頭に*をつけた項目のみ変更しました。

database.php
      'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            *'host' => env('DB_HOST', 'localhost'),
            *'port' => env('DB_PORT', '8889'),
            *'database' => env('DB_DATABASE', 'database_name'),
            *'username' => env('DB_USERNAME', 'root'),
            *'password' => env('DB_PASSWORD', 'root'),
            *'unix_socket' => env('DB_SOCKET', '/Applications/MAMP/tmp/mysql.sock'),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

このように設定してコマンドラインから以下のコマンドを実行したところエラー発生

$php artisan migrate
エラー内容
 Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] No such file or directory

エラーをみた感じどこかのpathが違うのかなと思いエラー内容を検索したところ、どうやら'unix_socket' => env('DB_SOCKET', '/Applications/MAMP/tmp/mysql.sock')の部分が関係ありそうとわかりました。
そう言えばXAMPPを使った時には/config/database.phpのこの部分をいじった覚えがなかったので、この記述について調べてみると、どうやらMAMPを使ってLaravelからDBに接続するにはTCP接続とUNIXドメインソケットを使用する方法の2通りがあるらしいということがわかりました。
【参考】Laravel5でデータベース接続にUNIXドメインソケットを使う

一応TCP接続が一般的ということでUNIXドメインソケットを使用するよりは簡単そうだと感じ、ひとまずUNIXドメインソケットを使用する方法は保留にしておくことにしました。
よくわからないものは書かない方が良いということで'unix_socket' => env('DB_SOCKET', '/Applications/MAMP/tmp/mysql.sock')の部分を削除し、またTCP接続をする場合にはDB_HOSTを localhostではなく127.0.0.1に変更する必要があるという記事を見つけて.env、/config/database.php共に修正をしました。

【参考】MySQLでlocalhostと127.0.0.1の違い

サーバーを再起動してから、再度以下のコマンドを実行したところ同じエラーが発生

$php artisan migrate
エラー内容
 Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] No such file or directory

修正した設定は絶対に正しいはずだったのでこうなってしまうとどこが違うかの検討もつかずお手上げでした。

解決方法

筆者は全く知らなかったのですが、どうやらLaravelではApacheを再起動した場合でも内部のキャッシュが残ってしまいプログラムを変更してもうまく反映してくれないことがあるそうです。

【参考】Laravel キャッシュクリア系コマンドなど

そこでコマンドラインから以下のコマンドを実行してキャッシュのクリアを行いました。

php artisan cache:clear
php artisan config:cache

.envファイルと/config/database.phpは以下のように記述

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_DATABASE=database_name
DB_USERNAME=root
DB_PASSWORD=root
database.php
   'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '8889'),
            'database' => env('DB_DATABASE', 'database_name'),
            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', 'root'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

DB接続の確認をするために以下のコマンドを打つとエラーが消えて実行することができたことから、DB接続が確認できました。

php artisan migrate

補足

以上の方法でDB接続をすることには成功したのですが、せっかくなので先ほど保留にしたUNIX_ドメインソケットを使用する方法にも挑戦しました。

UNIX_ドメインソケットを使用したDB接続(エラー編)  

.envファイルと/config/database.phpのDB_HOST127.0.0.1localhostに変更して、/config/database.phpのDB_SOCKETの部分を先の/Applications/MAMP/tmp/mysql.sockに設定をしました。
以下設定ファイル

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=8889
DB_DATABASE=database_name
DB_USERNAME=root
DB_PASSWORD=root
database.php
       'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '8889'),
            'database' => env('DB_DATABASE', 'database_name'),
            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', 'root'),
            'unix_socket' => env('DB_SOCKET', '/Applications/MAMP/tmp/mysql/mysql.sock
            '),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

このように設定ファイルを変更し、キャッシュをクリアしてサーバーを立ち上げ直し以下のコマンドを実行してDB接続ができているかを試したところまたしてもエラーが発生。
(DBを作り直すコマンドなので実行には注意)

php artisan migrate:refresh
 Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] No such file or directory

またこのエラーかということで詰みました。今回も変なところは見当たらないと思っていたのですが、ネットにあがっている記事を色々と見ていたところこのような記事を発見しました。

【参考】Laravelの.envファイルと、config/database.phpファイルについてのメモ

筆者は今まで設定ファイルの中のそれっぽい記述に飛びついて書いていたため全く意識してなかったのですが、config/database.phpのmysqlの設定部分は連想配列になっており、env()という関数に引数として.envファイルで設定した環境変数を渡す形のプログラムとなっています。また、env()の第二引数ではデフォルト値を渡しているそうです。

筆者は今までLaravelのDB接続設定で.envとconfig/database.phpの違いがよくわからないまま、どうしてDB接続の設定ファイルが二つもあるのかという風に思っていましたが、これに気づいて少し納得しました。
とはいえ実際に試してみないと曖昧なままなので、これを踏まえて先ほど成功したTCP接続で実験してみることにしました。

env関数の実験(TCP接続)

config/database.phpがenv()により.envで設定した環境変数の値を取得し、env()の第二引数はデフォルト値であるということは、.envさえ設定していればconfig/database.phpのenv関数の第二引数には何も渡さなくていいんじゃないかという予想を元に.envとconfig/database.phpを変更してみました。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_DATABASE=database_name
DB_USERNAME=root
DB_PASSWORD=root
database.php
    'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', ''),
            'port' => env('DB_PORT', ''),
            'database' => env('DB_DATABASE', ''),
            'username' => env('DB_USERNAME', ''),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

上記のように設定ファイルを変更して以下のようにコマンドを打ってキャッシュを削除します。

php artisan cache:clear
php artisan config:cache

サーバーを再起動してから、以下のコマンドを打つと実行できるようになり、DB接続が確認できました。

php artisan migrate:refresh

UNIX_ドメインソケットを使用したDB接続(解決編) 

要するに.envファイル内の記述がLaravelのDB接続の設定ファイルとしてはメインだということがわかったのですが、よくよく考えてみるとunix_socketに関する記述がデフォルトでは.envファイルの方に書かれていませんでした。
そこで試しに以下の一文を.envファイルに追加しました。

DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock

上の記述を追加した後の.envファイルの設定は以下のようになります。

DB_CONNECTION=mysql
DB_HOST=localhost
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock
DB_PORT=8889
DB_DATABASE=database_name
DB_USERNAME=root
DB_PASSWORD=root

/config/database.phpについては変更なしのままです。

database.php
 'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', ''),
            'port' => env('DB_PORT', ''),
            'database' => env('DB_DATABASE', ''),
            'username' => env('DB_USERNAME', ''),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

このように設定したら、再度キャッシュをクリアするコマンドを打ちます。

php artisan cache:clear
php artisan config:cache

サーバーを再起動して、以下のコマンドを打つと実行できたことから、DB接続が確認できました。

php artisan migrate:refresh

まとめ

本記事ではMAMPを使用したLaravelのDB接続についてエラーを解決するために色々試してみました。

長くなったので本記事のトピックをまとめます。

  1. MAMPを使う場合LaravelのDB接続方法にはTCP接続とUNIX_SOCKETを使用した接続がある
  2. Laravelではキャッシュをクリアしないと設定の変更が反映されないことがある
  3. TCP接続を使う際はDB_HOSTを127.0.0.1とする
  4. UNIX_SOCKETを使用して接続する際はDB_HOSTをlocalhostとし、DB_SOCKETを設定する
  5. config/database.phpで使われているenv関数は.envで設定した環境変数を取得する関数である
  6. UNIX_SOCKETを使用して接続する際は.envにDB_SOCKETを設定する文を追加する

終わりに

今まで、あまり内容を理解せずに行っていたLaravelのDB接続設定ですが、今回しっかりと向き合えたおかげで曖昧にしていた部分がよくわかりました。
また、今回はMAMPを使用しておりますが、XAMPPや他の方法でも同じように設定できるのかはわからなかったので後々実験してみようと思います。
本記事を作成する中で色々と試し理解したつもりではありますが、まだまだ理解の浅い部分や間違った解釈をしている部分があるかも知れません。そのような部分があった場合はご指摘いただけると幸いです。

また、初心者の方を対象にした記事になっていますが、記事を作成した筆者もまた、合間の時間を使って独学で学んでいる初心者です。筆者の話をすると、現在webプログラマーを目指して就職活動中ですが、未経験歓迎と書いてありながらも現場で働いている社員の方は即戦力になる人が欲しいと思っているのが本音なのか、どんなに熱心に準備をして望んでも興味なさそうに面接をされて落とされることもありました。
ただ、それはそれで仕方ないと筆者は割り切るようにしています。笑
しんどいことや辛いこともたくさんありますが、頑張っていきましょう!

参考サイト一覧

本記事の中で参考にさせていただいた記事を一度リンクを貼ったものも含めて再度掲載します。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
11
Help us understand the problem. What are the problem?