◀ 8.

LaravelのDotenv空白エラー|quote・変数展開と設定cacheの確認

▶

先に確認:Dotenvの構文エラーと設定の反映は別

スペースを含む値のquoteを閉じ、実際に使っているphpdotenv版の構文を確認します。quoteを直すことと本番で有効になるconfig値は別です。設定ファイル/秘密値の全文を公開せず、エラーの必要な行と供給元だけを調べます。

値の構文、環境変数の供給元、configの有効値を分ける図

quote・コメント・変数展開の例

以下は秘密情報のない検体です。phpdotenv5.7.0では単/両quoteで空白を含められます。単quoteは展開せず、両quoteの参照は先に定義した値から解決されます。quoteの選択は文字化け対策やpasswordの安全性そのものではありません。

APP_NAME="My App"
BASE_URL=https://example.invalid
DISPLAY="${APP_NAME} UI"
LITERAL='${APP_NAME} UI'
HASH_VALUE="abc#123"
EQUALS_VALUE=a=b=c
mixed_key=value
WINDOWS_PATH='C:\demo\project'
MULTILINE="line1
line2"
ESCAPED_NEWLINE="line1\nline2"

検体ではDISPLAYはMy App UI、LITERALは${APP_NAME} UIのまま、HASH_VALUEはabc#123、EQUALS_VALUEはa=b=c、小文字キーも成功しました。MULTILINEとESCAPED_NEWLINEはどちらも改行を含む値です。Windows pathの単quoteと両quoteのescape条件も区別し、対象版が違えば改めて確認します。Laravel8以降という境界だけでparserの全構文を決めません。

本体.envを読み込まないparse検体

次は既にvendor/autoload.phpがあるproject rootから実行する教材配置用のコードです。example.envは同じ教材folderにあるdummyデータで、利用者の.envを読みません。文字列のparse結果だけを返し、superglobalsの不変も確認します。実際のプロジェクトで使用する際はautoloadと検体の配置を合わせ、秘密値をこの出力へ含めません。

<?php
declare(strict_types=1);

// Run from a project root that already has vendor/autoload.php.
require getcwd().'/vendor/autoload.php';

$beforeEnv=$_ENV;$beforeServer=$_SERVER;
$result=['php'=>PHP_VERSION,'dotenv'=>Composer\InstalledVersions::getPrettyVersion('vlucas/phpdotenv'),
    'sample'=>Dotenv\Dotenv::parse(file_get_contents(__DIR__.'/example.env')),'cases'=>[]];
$cases=[
    'unquoted_space'=>"APP_NAME=My App\n",
    'single_quote'=>"APP_NAME='My App'\n",
    'double_quote'=>"APP_NAME=\"My App\"\n",
    'unquoted_hash'=>"VALUE=abc#123\n",
    'quoted_hash'=>"VALUE='abc#123'\n",
    'equals'=>"VALUE=a=b=c\n",
    'lowercase'=>"mixed_key=value\n",
    'unknown_reference'=>'VALUE="${NOT_DEFINED_IN_THIS_STRING}"'."\n",
    'bad_double_quote_escape'=>'VALUE="C:\Users\demo"'."\n",
];
foreach($cases as$name=>$text){
    try{$result['cases'][$name]=['values'=>Dotenv\Dotenv::parse($text)];}
    catch(Throwable$e){$result['cases'][$name]=['error'=>get_class($e)];}
}
$result['superglobals_unchanged']=$_ENV===$beforeEnv&&$_SERVER===$beforeServer;
echo json_encode($result,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR);

設定cache・外部envと有効値を分ける

段階確認した範囲
Dotenvのparse構文/参照を文字列だけで検証。Laravelアプリの起動/本番反映の成功ではない
Laravelで.env読込同名の外部環境変数等が優先され得る。fileだけの変更で値が変わるとは限らない
configがcache済み通常の.env読込をskipして保存されたconfigを使う。env()は外部envなら返せるため、常にnullではない

Laravel13.34.0の専用Application検体では、cacheなしは.env由来値、cacheありは保存値を返しました。cacheがあると不正な.envがあっても通常の読込みをskipできるため、起動成功だけで新しい.env構文が正しいとも言えません。外部env由来値はcache利用中も取得できました。実際のconfig:cache/clearコマンドや本番deployの実行検証ではありません。

CWiki本番ではconfig:clear単独実行は禁止で、変更は標準deployの設定再生成/本文疎通確認を含む手順で扱います。一般のLaravel記事でも、構文エラーの対処へoptimize:clearによる広い無効化や、稼働中の設定一律変更を自動追加しません。既存cacheを調査のためだけに導入/破棄する例でもありません。

APP_KEY・秘密値の扱い

APP_KEY未指定の表示が出ても、既存keyの供給元/利用中の暗号化データと運用手順を確認します。既存keyの上書き/再生成を自動対処にしません。quoteのためにpasswordから#を禁止するのではなく、対象parserに合うquoteとsecretの供給/保存を設計します。.gitignoreへ追加しても、すでに追跡/共有した秘密値が消えたり失効したりするわけではありません。

元の例と関連資料について

現在の7コード例/表の行/章を個別注意付きで保持し、元v2のエラー表示と単quoteの説明も戻します。shell向けのsourceやexportとDotenvの文法は同一ではありません。実行順/対象版/配置と有効なconfigを照合してください。

関連は実親Laravelエラー一覧とLaravelを参照してください。

既存の例と比較資料

この記事の要点
  • Laravel の Dotenv values containing spaces must be surrounded by quotes
  • 原因: .env ファイルで値にスペースを含めているがクォートで囲っていない
  • 対処: 対象parser版に合う単/両quoteを閉じ、展開とescapeの違いを確認
  • 構文の修正と有効なconfigの確認を分け、標準deployで反映する
  • スペース以外にも #(コメント開始)/ $(変数展開)/ 改行に注意

エラー内容

Laravel アプリを起動・実行時(php artisan serve や Web リクエスト時)に以下が発生:

旧例の注意:古い例外名/ソース配置の表示例です。現行5.7.0のparseではInvalidFileExceptionを確認しており、全版で同じtraceとは扱いません。秘密値を含む例外全文を公開しません。

RuntimeException
  Dotenv values containing spaces must be surrounded by quotes.

  at vendor/vlucas/phpdotenv/src/Loader/Parser.php:nnn

原因

.env ファイルで値にスペースを含むテキストをクォートなしで書いているのが原因:

旧例の注意:不正構文の例です。shellで実行せず、対象版のparserと行/quoteの対応を確認します。

# ❌ NG: スペースを含むのにクォートが無い
APP_NAME=My Awesome App
MAIL_FROM_NAME=Customer Support

# ❌ NG: クォートのバランスが崩れている
APP_NAME="My App

# ❌ NG: シングルクォートとダブルクォートの混在
APP_NAME='My App"

対処

スペースを含む値は、対象版に合う単quoteまたは両quoteで囲みます。変数展開/escapeの違いも確認します:

旧例の注意:Dotenvの記述例でbash scriptではありません。単quoteも使えます。quoteを文字化けやsecret保護自体と混同しません。

# ✅ OK: ダブルクォートで囲む
APP_NAME="My Awesome App"
MAIL_FROM_NAME="Customer Support"
APP_TIMEZONE="Asia/Tokyo"
APP_DESCRIPTION="サービスの説明文 ← 日本語スペースなくても安全のためクォート推奨"

# ✅ OK: スペースが無い値はクォート不要
APP_ENV=production
APP_DEBUG=false
DB_HOST=127.0.0.1

変更後の設定反映と確認

cacheされるconfigと、その供給元の.envを区別します。修正後の一律clearではなく、対象環境の正規deployと有効値/疎通確認を行います:

旧例の注意:このclear/optimize:clearは構文確認の読取ではありません。CWiki本番でconfig:clear単独を実行せず、広い無効化や設定上書きを通常対処へ自動追加しません。

php artisan config:clear

# 全部消したいとき
php artisan optimize:clear

# 本番では逆に config:cache でキャッシュを再生成
php artisan config:cache

シングルクォート vs ダブルクォート

ダブルクォート ""シングルクォート ''
変数展開○ ${APP_NAME} が展開される× リテラル文字列
エスケープ\n や \" が有効すべてそのまま
用途動的な値、他の変数を含む固定文字列、パスワード等

旧例の注意:phpdotenvの展開例です。shellのsource/exportと同一ではありません。参照の供給元/定義順/単quoteとの違いを対象版で確認します。

# 変数展開の例
APP_URL=https://example.com
APP_ASSET_URL="${APP_URL}/assets"  # → https://example.com/assets
# シングルクォートだと展開されない
APP_BAD='${APP_URL}/assets'        # → ${APP_URL}/assets (リテラル)

クォートが必要なケース

  • スペース: APP_NAME="My App"
  • # (コメント記号): PASSWORD="abc#123"(クォートなしだと abc までしか読まれない)
  • $ (変数展開): 展開させたくない場合は' を使う
  • =(イコール): DB_PASSWORD="a=b=c"等。5.7.0検体ではa=b=cは非quoteでも成功し、他の特殊文字と分けて判断
  • 日本語: quoteだけで文字化けを防ぐものではありません。文字コードと構文を分けて確認

複数行・改行を含めたい場合

.env での改行サポートはバージョン依存。対象Laravel/phpdotenv版の構文を確認し、Laravel8という境界だけで全parserの動作を決めません:

旧例の注意:改行/escapeはparser版依存です。5.7.0で実改行と両quote内\nを確認しましたが、単quoteの\nも同じとは扱いません。private keyの実値は公開しません。

# Laravel 8+ で動作(.env 内に直接改行)
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIE...
-----END PRIVATE KEY-----"

# 互換性重視: 改行を \n でエスケープ
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----"

config('xxx') 経由で取得

.env 値を直接 env('APP_NAME') で取らずに、config/app.php 経由で config('app.name') を使うのが Laravel 流:

旧例の注意:configの定義例と利用箇所は別ファイルです。cache済みでも外部envなら取得できるため、env()は必ずnullになると一般化しません。

// config/app.php
'name' => env('APP_NAME', 'Laravel'),  // .env が無いとデフォルト

// 各所で
config('app.name');         // 推奨
env('APP_NAME');            // 非推奨(config 外では空になる場合あり)

本番環境で php artisan config:cache を実行すると 通常の.env読込がskipされ、env()は外部環境変数なら返せます。常にnullとは限らず、アプリ内はconfig経由で有効値を扱います。

関連エラー

  • "Failed to parse dotenv file" — 構文エラー全般。クォートのバランス・改行コードを確認
  • "Encryption key (APP_KEY) not specified" — keyの供給元/既存暗号化データと運用手順を確認。既存keyの再生成/上書きを自動対処にしない
  • 「設定値が反映されない」 — 供給元/設定cache/対象環境を確認し、正規deployで反映/疎通確認する
  • ".env のキー名に小文字が混在」 — 小文字だけを理由にエラーと断定しない。5.7.0検体では小文字キーも成功し、利用側のキー名と規約を照合

予防

  • .env.example を必ずバージョン管理して、新メンバーがコピー → 設定変更だけで動かせるように
  • .env は .gitignore に必ず登録(機密情報のため)
  • 本番デプロイ時は CI/CD で .env を安全に注入(GitHub Actions Secrets / AWS SSM 等)
  • 秘密値を安全に供給する: #を一律禁止せず対象parserに合うquoteを選び、ログ/ソース/共有先への露出を防ぐ

元のエラー表示と単quoteの案内

元のエラー表記を保持します。スペースを含む値には対象版に合う単/両quoteを使い、単quoteだけが必須という元の説明には限定しません。

Dotenv values containing spaces must be surrounded by quotes. 

一次資料と検証範囲

PHP8.5.12/phpdotenv5.7.0の文字列parseと、Laravel13.34.0の空の専用Applicationでloaderの条件を確認。本番の.env/config/cache/認証鍵は変更せず、実deploy/全版/全worker/OS環境/暗号化データの復旧を保証しません。

子ページ

子ページはありません

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

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