12.

.env の値を取り出す方法(Laravel env / config / Node.js dotenv / PHP phpdotenv)

編集
この記事の要点
  • Laravel では コード内で env() を直接呼ぶのは禁止config() 経由で取得
  • 理由: 本番で php artisan config:cache を実行すると env()null を返すようになる
  • 正しい流れ: .env → config/*.php → config('app.name')
  • Node.js は require('dotenv').config()process.env.KEY
  • PHP 単体は Composer で vlucas/phpdotenv を入れ $_ENV['KEY'] で取得

.env とは

.env環境固有の設定値(DB パスワード、API キー、メールサーバ等)を、コードリポジトリに含めずに保存するためのファイルです。本番・ステージング・ローカルで値を切り替える際に使用します。

# .env の典型例
APP_NAME=MyApp
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp
DB_USERNAME=app_user
DB_PASSWORD=s3cret-passw0rd

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587

Laravel: env() と config() の使い分け(重要)

Laravel で 最も多い事故がここです:

// ❌ アンチパターン: コード中で env() を直接使う
class UserController extends Controller {
    public function index() {
        $appName = env('APP_NAME');     // 本番で null になる!
        return view('user.index', compact('appName'));
    }
}

// ✅ 正解: config() ヘルパーで取得
class UserController extends Controller {
    public function index() {
        $appName = config('app.name');  // config:cache 後も動く
        return view('user.index', compact('appName'));
    }
}

理由: 本番で php artisan config:cache を実行すると、Laravel は config/*.php 配下を bootstrap/cache/config.php に 1 ファイル化します。このとき $_ENV はロードされなくなり、env()null を返すようになります。一方 config() はキャッシュされた値を読むので問題なく動きます。

Laravel の正しいフロー

.env → config/*.php → config() で取得 の三段構成にします:

// 1) .env
STRIPE_SECRET_KEY=sk_live_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx

// 2) config/services.php
return [
    'stripe' => [
        'secret' => env('STRIPE_SECRET_KEY'),       // ← config/ 内なら env() OK
        'webhook' => env('STRIPE_WEBHOOK_SECRET'),
    ],
];

// 3) コード(Controller / Service / Job)
$secret = config('services.stripe.secret');         // ← ここは config() で
$webhookSecret = config('services.stripe.webhook');

env() ヘルパーの仕様

// 基本
env('APP_NAME');                          // string|null

// デフォルト値
env('APP_DEBUG', false);                  // 未定義なら false

// 型変換(文字列リテラル)
env('APP_DEBUG');     // .env に APP_DEBUG=true → (bool) true
env('FOO');           // .env に FOO=null     → (null) null
env('BAR');           // .env に BAR=empty    → (string) ''
env('BAZ');           // .env に BAZ=(true)   → (bool) true

// 値にスペース / 特殊文字を含めるならクォート
// .env
APP_NAME="My Cool App"
PASSWORD='p@ss"word'

本番デプロイの正しい手順

# 1) コード更新
git pull origin main
composer install --no-dev --optimize-autoloader

# 2) .env が正しいか確認
php artisan tinker
> config('database.connections.mysql.host')
# 値が表示されれば OK

# 3) 設定キャッシュを再生成(高速化)
php artisan config:cache
php artisan route:cache
php artisan view:cache

# .env を更新したら必ず
php artisan config:clear && php artisan config:cache

Node.js: dotenv パッケージ

npm install dotenv
// app.js の先頭で 1 回だけ呼ぶ
require('dotenv').config();

// 以降は process.env で取得
console.log(process.env.DB_HOST);
console.log(process.env.STRIPE_SECRET_KEY);

// デフォルト値
const port = process.env.PORT || 3000;

// 型変換は自分でやる
const debug = process.env.DEBUG === 'true';   // 文字列 'true' → bool
const maxConn = parseInt(process.env.MAX_CONN || '10', 10);

// ES Modules 版
import 'dotenv/config';
import dotenv from 'dotenv';
dotenv.config({ path: '.env.production' });

PHP 単体: vlucas/phpdotenv

composer require vlucas/phpdotenv
load();

// 取得(3 通り)
echo $_ENV['DB_HOST'];
echo $_SERVER['DB_HOST'];
echo getenv('DB_HOST');

// 必須キーの存在チェック
$dotenv->required(['DB_HOST', 'DB_USER', 'DB_PASS']);

// 型チェック
$dotenv->required('PORT')->isInteger();
$dotenv->required('APP_ENV')->allowedValues(['local', 'staging', 'production']);

Python: python-dotenv

pip install python-dotenv
import os
from dotenv import load_dotenv

load_dotenv()                          # カレントの .env を読む

db_host = os.getenv('DB_HOST')
db_port = int(os.getenv('DB_PORT', '5432'))
debug = os.getenv('DEBUG', 'False').lower() == 'true'

# Django なら settings.py で
# load_dotenv()
# SECRET_KEY = os.environ['SECRET_KEY']

.env を Git に含めないルール

# .gitignore
.env
.env.local
.env.*.local

# サンプルだけ共有
!.env.example

.env.example をリポジトリに置き、各開発者がコピーして使う運用が標準です:

cp .env.example .env
php artisan key:generate     # Laravel: APP_KEY を生成

よくあるトラブル

症状原因対処
本番だけ env() が nullconfig:cache 実行済コードを config() に直す
.env を変えても反映されないconfig キャッシュが古いphp artisan config:clear
値にスペースを含めると壊れるクォート無しKEY="My Value"
真偽値が文字列扱い"true" リテラルクォート無しで true と書く
artisan が boot で落ちる.env が壊れているphp artisan tinker で確認

FAQ

Q: なぜ env() を直接使ってはいけないのか
A: config:cache 後の本番で null を返すから。「ローカルで動いて本番で死ぬ」最頻バグです。

Q: .env を暗号化したい
A: Laravel 9+ は php artisan env:encrypt / env:decrypt でファイル単位の暗号化に対応しています。

Q: 環境別に値を分けたい
A: .env.local / .env.staging / .env.production を作り、デプロイ時にコピー or シンボリックリンクで切り替えるのが一般的です。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストールと設定
  2. クイックスタート & チュートリアル(初心者向け)
  3. クイックスタート & チュートリアル(中級者向け)
  4. ルーティング
  5. Bladeテンプレート(ビュー/レイアウト)
  6. コントローラー
  7. マイグレーションとテーブル定義
  8. データベースの設定
  9. Eloquentモデル (ORM)
  10. SQLとクエリビルダー
  11. バリデーション
  12. .envファイルの設定値へのアクセス
  13. 動作環境による分岐処理
  14. configフォルダ配下の設定値へのアクセス
  15. assetヘルパーを利用したpublicフォルダへのアクセス
  16. storageフォルダへのアクセス
  17. アプリケーション名の変更
  18. メンテナンス
  19. ログイン画面(認証システム)の作成
  20. ログインの必須化
  21. ログインユーザー情報の取得
  22. ルートの認証化
  23. 本番サーバーへのデプロイ方法
  24. 多言語化
  25. csrf_field
  26. ファイルのダウンロード
  27. CSVのアップロードおよび読み込み(maatwebsite/excel)
  28. ページタイトルの設定
  29. コマンド一覧
  30. エラー一覧
  31. SQLの実行ログ出力方法
  32. キャッシュのクリア
  33. Selectの結果の最初もしくは最後に任意の値を追加する方法
  34. ajaxでPOST通信する際の注意点
  35. ソーシャルログインの実装
  36. セッション情報の確認
  37. ログイン、ユーザー登録、パスワードリセット後のリダイレクト先の変更方法
  38. redirectやreturn viewにメッセージを付与する方法
  39. クッキー(cookie)の設定と取得
  40. クラスの再読み込み
  41. csrfの有効時間を変更する方法
  42. ViewComposerを用いてviewに共通の値を付与する方法
  43. View::shareを用いて共通の値を各ビューに渡す方法
  44. ミドルウェアを用いた処理の共通化
  45. Middleware内でAuth::check()などを使用する方法
  46. Controller以外でリダイレクトする方法
  47. セッションの値の取得/保存/更新/削除
  48. $requestの値を変更する方法
  49. 常時SSL化
  50. ページング(ページネーション)をする方法
  51. vue.jsとの連携
  52. Vue.jsと連携するSPA実行環境構築
  53. .envの値をvue.jsで参照する方法
  54. vue.jsを本番環境にリリースする方法
  55. could not find driver(Windows, MySQL編)