1.

LaravelのMySQL 1045|有効設定・接続先・認証の確認

▶

LaravelからMySQLへ接続する際の1045を、設定・接続先・認証と、接続後の権限に分けて確認します。接続確認のためにmigrateを実行したり、ユーザーへ全権限を与えたりする必要はありません。

laravelの有効設定と接続先・認証を確認し、接続確認とschema変更を分ける図

1045の表示から分かること・分からないこと

using password: YESはパスワードを送ったという情報で、パスワードだけが原因と確定する意味ではありません。隔離検体では、間違ったパスワードでも存在しないユーザーでも1045/YESになりました。NOはパスワードを使わない接続要求で、必ず.envの読込失敗という意味ではありません。ユーザー名/接続元、認証方式、対象サーバー、アカウント状態などを分けて調べます。

まず有効な接続名・設定の供給元を確認する

.envの文字列だけでなく、実際のデフォルト接続と、その接続のconfigを確認します。モデルや処理が別名の接続を選ぶ場合もあります。DB_URLを参照する設定ならURL側の値、サーバーから与えられる環境変数、read/write用の上書き、設定キャッシュも確認対象です。パスワードや接続URL全体を画面・質問サイト・ログへ出さないでください。

設定をキャッシュした環境では.envが通常のリクエスト/Artisanでロードされないため、.envを直しただけで反映したとは限りません。隔離検体では、正しい.envでも古いキャッシュのパスワードが残れば1045となり、逆にキャッシュが正しければ別の.env値は使われませんでした。外部環境変数とURLによる上書きも別々に確認しています。

schemaを変えずに接続結果を確認する例

次は承認済みのLaravel管理コンテキスト用です。CWiki本番や他人のDBへ試す例ではありません。意図したMySQL/MariaDB接続だけを選び、認証アカウント・DB名・版・セッションsql_modeを読みます。失敗時は生の例外本文を出さずコードだけ返します。出力のhost/user等も内部情報なので、そのまま公開しません。

<?php
// Authorized local/management context only. Do not publish this output.
// No password, full URL, raw exception message, DDL, or application table reads.
$name = config('database.default');
$connection = Illuminate\Support\Facades\DB::connection($name);
$resolved = $connection->getConfig();
$result = [
    'connection' => $name,
    'config_cached' => app()->configurationIsCached(),
    'driver' => $resolved['driver'] ?? null,
    'host' => $resolved['host'] ?? null,
    'port' => $resolved['port'] ?? null,
    'database' => $resolved['database'] ?? null,
    'username' => $resolved['username'] ?? null,
    'password_configured' => ($resolved['password'] ?? '') !== '',
];
try {
    if (!in_array($result['driver'], ['mysql', 'mariadb'], true)) {
        throw new RuntimeException('Choose the intended MySQL/MariaDB connection');
    }
    $connection->getPdo();
    // false selects the write connection, not a potentially different read host.
    $result['server'] = $connection->selectOne(
        'SELECT VERSION() AS server_version, DATABASE() AS database_name, CURRENT_USER() AS authenticated_account, @@SESSION.sql_mode AS sql_mode',
        [], false
    );
    $result['ok'] = true;
} catch (Throwable $error) {
    $result['ok'] = false;
    $result['exception'] = get_class($error);
    $cause = $error;
    while ($cause->getPrevious() !== null) {
        $cause = $cause->getPrevious();
    }
    $result['sqlstate'] = $cause instanceof PDOException ? ($cause->errorInfo[0] ?? null) : null;
    $result['mysql_code'] = $cause instanceof PDOException ? ($cause->errorInfo[1] ?? null) : null;
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), PHP_EOL;

この例はgetPdo()とselectOneの第3引数falseでwrite側の接続を調べます。readレプリカや複数host、実アプリの全クエリ経路を確認するものではありません。configに出たhostだけで実ネットワーク経路まで証明せず、接続先が意図したものか管理者の情報と照合します。

認証成功と業務操作の許可を分ける

接続とSELECTに成功しても、INSERTやCREATE TABLEまで許可された意味ではありません。今回の新規検体ではSELECTだけを与えたアカウントで読取が成功し、INSERT/DDLは拒否されました。必要な表・操作に限定して管理者へ確認し、1045に対する通常対処としてGRANT ALLや%アカウントの追加、認証pluginの差し戻しを行いません。

設定変更・常駐処理・Dockerは別に計画する

config:clearは一般のLaravelでは設定キャッシュを消すコマンドですが、本番は所有者の正式な配備手順で再生成と正常性を確認します。特にCWikiでは単独実行しません。全コンテナ再起動をエラーの第一手にせず、長時間動作するworker等へ設定をどう反映するかを実行形態ごとに計画します。今回、本番cache/プロセスは変更していません。

Docker内の127.0.0.1はそのコンテナ自身です。DB_HOSTは実compose/network/接続経路から決め、Sailのサンプル名・ユーザー・公開パスワードを全環境の固定値としません。MySQL公式コンテナの初期化設定を変えても、既存DBのパスワードが自動で変わるわけではありません。接続失敗を理由にvolumeを消さないでください。

以前の例と補足

以下のコード/章は保持していますが、接続確認とschema変更を混ぜないよう、誤った説明と要約表は訂正し、各例にも条件を添えています。古いHomesteadの公開値を実運用へ流用しません。

旧例の注意:要約は有効設定/対象確認へ訂正済みです。cache削除/新規ユーザー/広いGRANTへの自動案内ではありません。

この記事の要点
  • Laravel から MySQL に接続したとき、ユーザー名またはパスワードが MySQL 側で認められないと出るエラー
  • 'homestead' は Laravel の古い .env.example の初期値。有効なDB接続設定と対象サーバー/アカウントを照合する。不一致は原因候補の一つ
  • .env を直しても変わらないときは設定キャッシュや外部環境/URLも確認。本番は正式な配備手順で更新
  • Docker / SailのDB_HOSTは実network/接続経路から決める。サービス名mysqlは例で固定値ではない
  • MySQL 8 以降は GRANT ... IDENTIFIED BY が使えない。CREATE USER してから GRANT する
  • まず mysql コマンドで同じユーザー・パスワード・ホストで接続できるかを確かめる

エラー内容

旧例の注意:元の表示例です。YESだけをパスワード不一致の証拠とせず、アカウントや接続先を確認します。

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

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

YESはパスワードを使った接続要求を示し、不一致だけを確定するものではありません。NOも必ず.envの読込失敗とは限りません。実際のユーザー/接続先/アカウント条件を確認します。

原因

ユーザー名が 'homestead' になっているのは、Laravel の古いバージョンの .env.example に、開発用仮想環境 Laravel Homestead 向けの初期値(ユーザー homestead / パスワード secret)が書かれていたためです。Homestead向けの公開値が残っている可能性はありますが、名前だけで未作成と断定しません。対象環境の設定を照合し、そのユーザーを新規作成して合わせる対処にしません。

旧例の注意:原因候補の表です。ログインできないことと、接続後の表操作権限を分けます。%がある場合にlocalhostアカウントを追加すればよいとは扱いません。

原因見分け方
.env の DB_USERNAME / DB_PASSWORD が実際の DB と違うエラーのユーザー名が 'homestead' や 'root' など想定外になっている
設定キャッシュが古い値のまま.env を書き換えてもエラーのユーザー名が変わらない
アカウント/認証の条件と、接続後のSQL操作権限を区別mysql コマンドでも同じユーザーでログインできない
接続元ホストが合っていない実際に照合されるUser/Hostと接続経路を確認。localhostがないだけで失敗と決めない
パスワードの記号が .env で正しく読まれないパスワードに # や空白、引用符が含まれている
Docker 環境で接続先を間違えているコンテナ内から 127.0.0.1 に接続し、別の MySQL に当たっている

対処法

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

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

旧例の注意:公開Homestead初期値の記録です。実運用へ流用せず、存在しないDB/ユーザーを検証のために作りません。

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

自分で作った DB を使う場合は、たとえば次のように書き換えます。記号/引用符/変数展開はphpdotenvの対象版/構文で確認します。ダブルクォートだけで全秘密値が安全に解釈されるとは扱いません。

旧例の注意:公開された仮の秘密値です。全環境でこの引用形式にすれば安全という保証ではなく、実プロジェクトのparser/展開を確認します。

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

配布skeletonや生成オプションによってSQLite等が選ばれる場合もあります。実プロジェクトの接続定義を確認し、既存環境をこのサンプルへ一括変更しません。

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

過去に php artisan config:cache を実行していると、Laravel は .env ではなく bootstrap/cache/config.php の値を使います。.envの変更だけで反映されたと扱わず、本番は所有者の正式な配備手順で更新/正常性を確認します。次の旧操作を単独の本番対処にしません。

旧例の注意:config:clearだけで本番を終えません。CWikiでは単独実行を禁止しており、正式deployに従います。この作業では既存アプリの設定cacheを削除していません。

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

長時間動作するworker等は設定を保持することがあります。実行形態と正式な更新方法を確認し、全Dockerコンテナや全プロセスの再起動を必須の第一手にしません。

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

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

旧例の注意:CREATE DATABASE/USERとGRANT ALLは設定変更です。1045を直すために一括実行せず、アプリ用とschema変更用の必要権限を分けます。公開パスワードも使いません。

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 で確認できます。

旧例の注意:mysql.userを読む権限が必要です。plugin等の情報を公開せず、パスワード情報や全アカウントを取得する例へ拡張しません。

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/passwordは公開された構成例で、全Sail環境の固定資格情報でも実運用の推奨でもありません。また MySQL コンテナはデータボリュームが空のときだけ環境変数からユーザーを作るため、後から .env のパスワードを変えても既存のボリュームには反映されません。

確認方法

  1. .env と同じ値で mysql コマンドから接続できるか確かめます。同じ実行環境/通信経路と認証条件で比べます。クライアントの既定optionやTLS等も異なり得るため、単独の結果で全原因を断定しません

旧例の注意:-pは対話入力で、実秘密値を引数へ付けません。CLIの実行場所・既定option・socket/TCP/TLSとアプリの条件を合わせます。

mysql -h 127.0.0.1 -P 3306 -u myapp_user -p myapp
  1. Laravel が実際に読み込んでいる設定値を確認します

旧例の注意:tinkerの読取例です。DB::connection()の実接続名も確認し、PDOオブジェクト全体を公開しません。成功後にmigrateへ自動的に進みません。

php artisan tinker
>>> config('database.connections.mysql.username')
>>> DB::connection()->getPdo();

getPdo() がエラーなく PDO オブジェクトを返せば接続は成功しています。接続確認のためにmigrateを実行しません。業務SQLとschema変更の可否/承認は別に確認します。

よく似た別のエラー

  • 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 認証になっているケースです

関連

参考:旧構成の書式付き例

元例の注意:元の1045表示です。ユーザー/接続元の情報だけで全原因を確定せず、実際のメッセージを確認します。

SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost'

元例の注意:元はmigrate中に発生した記録です。エラー再現/接続確認のためにmigrateを実行する推奨ではありません。

php artisan migrate

元例の注意:Homesteadの公開初期値の記録で、実環境へ追加するアカウント/秘密値ではありません。

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

確認範囲と関連ページ

2026年10月26日確認。PHP8.5.12/Laravel13.34.0のvendor bootstrap/PDOとPython3.12.10/Django5.2.18/mysqlclient2.2.7を、新規ローカルMySQL8.4.13の検体にだけ接続しました。新しい掲載ソースの読取、認証1045と操作拒否1142、設定の優先関係、schema/データ/権限の前後不変を確認しています。Laravel全アプリのbootstrap/HTTP/FPM/worker、PyMySQL/MariaDB/全版、実TLS/ASGI/レプリカ、実環境の秘密管理/本番配備は未検証です。CWiki本番のDB設定/認証/権限/接続先を変更せず、config:clearやmigrateを実行していません。

Laravelエラー一覧の子ページから選択できます。設定はデータベースの設定と.envを参照します。

一次資料:Laravelの外部環境変数と設定キャッシュ、Laravelの接続設定とURL解析、Django5.2のdriver/接続/持続接続、Djangoのaliasとルーターの制限、MySQLの接続エラーとpassword表示、MySQL SET文。

子ページ

子ページはありません

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

最近更新/作成されたページ