1.

SQLSTATE[HY000] [1045] Access denied for user の対処

▶
この記事の要点
  • Laravel から MySQL に接続したとき、ユーザー名またはパスワードが MySQL 側で認められないと出るエラー
  • 'homestead' は Laravel の古い .env.example の初期値。.env の DB_USERNAME / DB_PASSWORD が実際の DB と一致していないのが最も多い原因
  • .env を直しても変わらないときは設定キャッシュを疑う(php artisan config:clear)
  • Docker / Sail では DB_HOST が 127.0.0.1 ではなくサービス名(例: mysql)になる
  • MySQL 8 以降は GRANT ... IDENTIFIED BY が使えない。CREATE USER してから GRANT する
  • まず mysql コマンドで同じユーザー・パスワード・ホストで接続できるかを確かめる

エラー内容

SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES)

Laravel で php artisan migrate を実行したときや、DB にアクセスするページを開いたときに発生します。1045 は MySQL のエラー番号で「認証に失敗した」ことを意味します。DB サーバーまでは届いているが、ユーザー名・パスワード・接続元ホストの組み合わせが認められなかった状態です。

末尾の (using password: YES) はパスワードを送ったが一致しなかったこと、(using password: NO) はパスワードが空のまま接続しようとしたことを表します。NO になっている場合は DB_PASSWORD が読み込まれていない可能性が高いです。

原因

ユーザー名が 'homestead' になっているのは、Laravel の古いバージョンの .env.example に、開発用仮想環境 Laravel Homestead 向けの初期値(ユーザー homestead / パスワード secret)が書かれていたためです。Homestead を使っていない環境でこの値のまま接続すると、MySQL にそのユーザーが存在せずエラーになります。

原因見分け方
.env の DB_USERNAME / DB_PASSWORD が実際の DB と違うエラーのユーザー名が 'homestead' や 'root' など想定外になっている
設定キャッシュが古い値のまま.env を書き換えてもエラーのユーザー名が変わらない
MySQL にユーザーが作られていない・権限がないmysql コマンドでも同じユーザーでログインできない
接続元ホストが合っていない'user'@'%' はあるが 'user'@'localhost' はない、などホスト部分が違う
パスワードの記号が .env で正しく読まれないパスワードに # や空白、引用符が含まれている
Docker 環境で接続先を間違えているコンテナ内から 127.0.0.1 に接続し、別の MySQL に当たっている

対処法

1. .env の DB 設定を実際の値に直す

プロジェクトのルートディレクトリ直下にある .env ファイルの DB 設定を、実際に使う MySQL の値に変更します。以下は Homestead の初期値の例です。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

自分で作った DB を使う場合は、たとえば次のように書き換えます。パスワードに # や空白などの記号を含む場合は、ダブルクォートで囲むと安全です。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp
DB_USERNAME=myapp_user
DB_PASSWORD="p@ss#word"

なお Laravel 11 以降の新規プロジェクトは初期状態で DB_CONNECTION=sqlite になっています。MySQL を使う場合は DB_CONNECTION を mysql に変え、DB_HOST 以下の行のコメント(先頭の #)も外します。

2. 設定キャッシュをクリアする

過去に php artisan config:cache を実行していると、Laravel は .env ではなく bootstrap/cache/config.php の値を使います。.env を直しても反映されないときは、キャッシュを消します。

php artisan config:clear
# 本番環境では、確認後にあらためてキャッシュを作る
php artisan config:cache

php artisan serve や Docker コンテナ、キューワーカーなど常駐しているプロセスは、起動時の設定を持ち続けるので再起動も必要です。

3. MySQL 側にユーザーと権限を作る

ユーザーが存在しない場合は、MySQL に管理者でログインして作成します。MySQL 8.0 以降は GRANT 文でユーザー作成とパスワード設定を同時に行う書き方(IDENTIFIED BY 付きの GRANT)が廃止されたため、2 段階で実行します。

CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'p@ss#word';
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp_user'@'localhost';
-- 既存ユーザーのパスワードを変える場合
-- ALTER USER 'myapp_user'@'localhost' IDENTIFIED BY '新しいパスワード';

MySQL のユーザーは「ユーザー名+接続元ホスト」の組で管理されます。'myapp_user'@'localhost' と 'myapp_user'@'%' は別のユーザーとして扱われ、パスワードも別々です。どのホストで登録されているかは次の SQL で確認できます。

SELECT user, host, plugin FROM mysql.user WHERE user = 'myapp_user';

4. Docker / Laravel Sail の場合

Laravel Sail や docker compose で MySQL を動かしている場合、アプリのコンテナから見た 127.0.0.1 はアプリのコンテナ自身です。DB_HOST には compose ファイルのサービス名(Sail の初期値は mysql)を指定します。Sail の初期ユーザーは sail / パスワード password です。また MySQL コンテナはデータボリュームが空のときだけ環境変数からユーザーを作るため、後から .env のパスワードを変えても既存のボリュームには反映されません。

確認方法

  1. .env と同じ値で mysql コマンドから接続できるか確かめます。ここで失敗するなら Laravel ではなく MySQL 側の問題です
mysql -h 127.0.0.1 -P 3306 -u myapp_user -p myapp
  1. Laravel が実際に読み込んでいる設定値を確認します
php artisan tinker
>>> config('database.connections.mysql.username')
>>> DB::connection()->getPdo();

getPdo() がエラーなく PDO オブジェクトを返せば接続は成功しています。最後に php artisan migrate を実行してエラーが出ないことを確認します。

よく似た別のエラー

  • SQLSTATE[HY000] [2002] Connection refused: 認証以前に DB サーバーに届いていません。MySQL の起動状態や DB_HOST / DB_PORT を確認します
  • SQLSTATE[HY000] [1049] Unknown database: ログインはできたが DB_DATABASE の DB が存在しません
  • ERROR 1698 Access denied for user 'root'@'localhost': Ubuntu などで root が auth_socket 認証になっているケースです

関連

Post Share
子ページ

子ページはありません

同階層のページ
  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が返却される問題