どーも!
今回はLaravelでの環境変数の使い方を調べてみます。
目次
環境変数って?
さて、それではまずは環境変数・・・よく聞きますが一体なんなんでしょうか・・・?
正直みなさんご存知かもしれませんが念のため...
プログラムにおける環境変数は例えばプログラム全体で共通して使用する環境値(使用しているDBの情報、サービスで使用するメールアドレスの情報...)等、そのサービス自体にあまり関係のない、周りの環境要素の値を入れておくための変数です。
そうしておけば、今後使用するDBが変わった!とか、メールアドレス送信先変わった!とかなっても変更しやすくなるわけです。
俗に言うPCの環境変数(パスのやつ)と似ていますが、あちらは基本的に実行ファイルがあるパス等、ファイルパスを設定することが多いですね。
元を辿れば、どちらも同じで、その環境変数の値をプログラムが使用していろんなことゴニョゴニョやっているんですが...
とにかく、いろんな値を設定して便利に使えるんです!
では、次節からlaravelでの使い方をみていこうと思います!
Laravelで環境変数を使う方法
さて、ではlaravelでの環境変数の使い方をみていきましょう!
環境変数の定義
基本的にlaravelでは.envファイルというファイルに対して環境変数を定義していきます。
environmentという"環境"の英語からきています。
ちなみに、laravelだけでなく、割と様々な他のフレームワークでもenvファイルという型で環境変数が使われています。
その.envファイルはプロジェクトフォルダ直下にあるはずです。(MyProject/.env
)
そのファイルをみてみると...?
APP_NAME=Laravel
APP_ENV=local
APP_KEY=********
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=takapon-test
DB_USERNAME=takapon
...
こんな感じになっているはずです。
DB関連の情報は僕の場合、psql用に書き換えています。
基本的に環境変数名は上記のように大文字のスネークケース(SNAKE_CASE)で記述します。
そして、実際の値をそのままその変数へ代入する形です。
今回は検証のために適当に名前をつけて一個追加してみましょう。
...
TEST_TAKAPON=tektektech
...
こうすることで、環境変数の値をこのプロジェクト中で使用することができるようになります。
環境変数を使用してみる
さて、では今適当に定義した環境変数をプログラム側で使えるかちゃんと確認してみます。
先ほどの変数を呼び出す方法は以下のようになります。
$tech = env('TEST_TAKAPON');
このenvメソッドに対して、環境変数名を引数に渡してあげればその値が取得できます。
では、ちゃんとこの値が取得できるか確認します。
Tinkerを使用して確認してみます。
Takapon:MyProject taka$ php artisan tinker
Psy Shell v0.10.3 (PHP 7.3.9 — cli) by Justin Hileman
>>> env('TEST_TAKAPON');
=> "tektektech"
>>>
ちゃんとtektektech
と出ました!
ちなみに、Tinkerの使い方は以下でご確認ください。
今回のようにちょっとしたプログラムの動作確認に非常に便利です。
さて、基本的な環境変数の呼び出しができることを確認しました。
では次に、公式でも解説されていますが、envの値が存在しない場合に返すデフォルト値を設定してみます。
もしも環境変数を間違って消してしまったり、消したあとにプログラム側でenvの参照を修正し忘れてしまった場合などに値がないからデフォルト値で無害な値や、不整合に気付きやすいよう開発者のメールアドレスを設定したりすることで有効に使えそうです。
定義側はそのままで、呼び出し側を以下のように変えてみます。
env('TEST_TAKAPOON','error');
第一引数に存在しない環境変数を、そして第二引数に環境変数が存在しない場合に返して欲しいデフォルト値を設定しました。
この状態で再度tinkerにて実行してみると...?
>>> env('TEST_TAKAPOON','error');
=> "error"
定義した環境変数はTEST_TAKAPON
ですが、今回呼び出そうとしているものはTEST_TAKAPOON
で、そんな環境変数は存在しません。
すると、意図したものがなかったため、第二引数に与えている文字列が出力されるわけですね。
上記が基本的な環境変数の使い方です。
では、次はそんな環境変数を使用する際に気をつけなければいけないことがあるので、それについて調べておきます。
envファイルは直接参照しちゃダメ!
さて、環境変数の基本的なことはもう理解していただけたと思いますが、ことlaravelにおいてはもう一ひねり気をつけないといけないことがあります。
先ほど環境変数をenvメソッドで".env"ファイルから環境変数を参照していました。
実はあれ...
やたらめったら使ってしまうと...
ダメなんです...
確かに手元で試したらちゃんと動きました。
では何がダメなんでしょうか・・・?
それについて述べていきます。
直接参照することの何がいけないの?
laravelでは設定ファイル(プロジェクト直下のconfigディレクトリ内)をより素早く扱えるようにキャッシュする機構があります。
キャッシュとは、すごく大雑把に説明すると、使用頻度の高い情報等を初回のロードで溜め込んでおき、2回目以降はロードをせず、溜め込んでいる手元の情報から使う機能です。
そのキャッシングの作業自体は以下のartisanコマンドで実行が可能ですが...
$ php artisan config:cache
Laravelの公式の日本語訳をみてみると...
開発過程の一環として
Laravel Readouble 設定 6.xconfig:cache
コマンド実行を採用する場合は、必ずenv
関数を設定ファイルの中だけで使用してください。設定ファイルがキャッシュされると、.env
ファイルはロードされなくなり、env
関数の呼び出しはすべてnull
を返します。
特に二段落目に注目してください。
設定ファイル(config内のファイル)がキャッシュされると、config外にある".env"ファイルはロードされなくなってしまい、env関数の呼び出しがnullになってしまいます。
そこで、このconfig内はちゃんとキャッシュするので、この設定ファイル(configフォルダの中にあるファイル)でのみ、envメソッドを使うようにしてね!
と言うわけですね。
そもそもキャッシングをしなければどこでenvメソッドを使っても大丈夫なんですが、公式としてもやはりキャッシングはすべきと記載があります。
これは単純にプロジェクトが大きくなればなるほど設定ファイルも増え、毎回必要な際に全ての設定ファイルをロードしていたら処理が遅くなるのは目に見えていますね。
では、.envの環境変数はconfigをキャッシュすると使えないんでしょうか・・・?
もちろん、使えます。
再度引用しますが...
開発過程の一環として
config:cache
コマンド実行を採用する場合は、必ずenv
関数を設定ファイルの中だけで使用してください。
この通り、"envメソッドをconfigのファイル内で呼び出す"のは問題ないんです。
そこで、一旦envファイルの呼び出しはconfigで行って、その呼び出した結果の変数へ別のあらゆる場所から読み込むようにすれば大丈夫なんですね。
それでは実際にやってみましょう!
configで.envの環境変数を定義する
configファイルはプロジェクトフォルダの直下(appやresourceと同じ階層)にあるはずです。
筆者の環境だと以下のような感じでした。("MyProject"は各自のlaravelのプロジェクト名になります)
一般的に.envの中身をconfigを経由して使う場合は"config/app.php"ファイルが使用されるので、今回もそこへ記載していきます。
さて、ではapp.phpを開いてみると...
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
|
*/
'name' => env('APP_NAME', 'Laravel'),
このような感じのファイルになっているはずです。
いきなりreturnが書かれていて気持ち悪い気もしますが、この設定ファイルは配列を返すように書かれています。
配列の要素として使いたい変数名をキー(使う側で呼び出す際に使う名前)と実際の値(envファイルから持ってきたりベタ打ちしたり)として定義していきます。
早速見えていますが...以下が実際に定義している例ですね。
// 使う側では'name'として呼び出し、値は.envファイルの'APP_NAME'の値
'name' => env('APP_NAME', 'Laravel'),
第二引数がありますが、これは先ほどのenvファイルの呼び出しでやりましたね。
もしもenvファイルにAPP_NAMEの値がなければ'Laravel'という値を返す。と言う意味です。
ではこれに倣って先ほどの例を使って定義してみます。
定義する順番などは正直どこでもいいんですが、app.phpに書く場合、例えば以下のようにコメントでわかるようにしておくとLaravelの本来の設定と混ざらないため、わかりやすいと思います。
ただし、おまけにて解説しますが、別ファイルで定義する方がより綺麗だとは思います。
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
|
*/
'name' => env('APP_NAME', 'Laravel'),
/*
|--------------------------------------------------------------------------
| 非デフォルトenv定義箇所
|--------------------------------------------------------------------------
|
| Laravelのデフォルト定義ではないenvの設定は以下に記載すること。
|
*/
'tech' => env('TEST_TAKAPON','error');
...
文章は適当です...w
今回、techと言う名前で先ほどenvに設定した値を参照できるように定義しました。
これで使う準備は万端です。
configの値をプロジェクト内の他のファイルから参照する
さて、それではいよいよ定義したconfigの値を使ってみましょう!
ただ、これもとっても簡単です。
先ほどenvメソッドを使ったと思いますが、それとほとんど同じなんです。
口で言うよりみてもらった方が早いので、以下のコードをご覧ください。
$tech = config('app.tech');
みていただけるとわかりますが、外から設定ファイルを参照するためのconfigメソッドがあります。
引数に呼びだしたい設定値を指定するんですが...
呼び出し時の名前は"tech"に設定したはずが、"app.tech"になっていますね。
これは単純にその設定値(tech)の定義が書かれているファイル名(app.php)から拡張子(.php)を除いたもの(app)を付ければ大丈夫です。
こうすることで、appファイルのtechっていう値を使うよ!って指定できるわけです。
では実際に使ってみましょう!
今回、先ほど述べた通り、キャッシュした値を読み込むので、使う前に設定した値をキャッシングしておかないといけません。
// キャッシュしていない状態でTinkerで確認しようとした
>>> config('app.tech');
=> null
// Tinkerを閉じてキャッシングを実行
Takapon:MyProject taka$ php artisan config:cache
Configuration cache cleared!
Configuration cached successfully!
// キャッシュがある状態でTinkerを確認
>>> config('app.tech');
=> "tektektech"
>>>
キャッシュした状態で実行してみるとちゃんと".env"に設定した値がconfigを経由して取得できました!
キャッシュがない場合をみていただくと、nullになっています。
仮に設定ファイルに値を設定して、envがない場合のデフォルト値(今回は"error")を設定していてもnullが帰ります。
考えてみればわかることですが、"キャッシュが無い=設定ファイルの設定が反映がされていない"わけです。
つまり...このファイルを書き換えた場合、その書き換えた分のキャッシュはそれだけでは反映されません。
都度、前述したconfig:cache
コマンドを実行する必要があります。
これが俗に言う"設定ファイル変えたのに変わってないわー現象"です笑
おまけ
さて、前の例では"app.php"というファイルに対して定義をしましたね。
ただ、configの中には別の名前のファイルもたくさんあります...
そうです。
設定は...好きなファイルに書くことができるんです!
簡単にやってみます。
configフォルダ配下にさらにフォルダを作って...
"config/hoge/huga/tech.php"というファイルを作りました。
その中に以下のようにベタ打ちで定義をします。(値はenvメソッドで参照しても大丈夫です)
<?php
return [
'tech' => 'これはtech.phpで定義した値です',
];
たった一つの変数を定義しているだけですね。
この状態で再度キャッシュを作成して...
tinkerで確認をしてみると...?
>>> config('hoge.huga.tech.tech');
=> "これはtech.phpで定義した値です"
みれました...!
あえて説明のため複雑なファイル階層にしたんですが、上記のようにフォルダー間の繋がりを"."でつなぎ、そしてファイル名と変数名も"."でつなぐことでより深い設定ファイルも参照することが可能です。(これをドット記法と言うらしいです)
先ほどの例は"config/app.phpのtechと言う値"へのアクセスだったので、"app.tech"になりました。
今回の例は"config/hoge/huga/tech.phpのtechという値"へのアクセスだったので、"hoge.huga.tech.tech"になりました。
もし仮にtech.phpがapp.phpと同じ階層なら...
"tech.tech"になりますね。
このように、別のファイルを用意して配列をreturnするように定義すればファイルを分けることも可能です。
そうすると、appに全ての設定値をかくのではなく、例えばプロジェクト内の細かい役割ごとに設定ファイルもフォルダ分けして整理した方がわかりやすくなるでしょう。
まとめ
今回は環境変数について色々とまとめてみました。
公式ページに全部載っている内容なんですが、実際読んでみるとな〜んかわかりづらかったりしますよね...
そして環境変数周りのことはよく新人が悩まされます...
envメソッドを使ってレビューでconfigを使うように指摘を受けたり...(当時はなぜダメなのか知らなかった...
envを定義してなぜか反映されない...
これら、実際に僕、去年の一年間で何度もありました...w
実際に皆さんも手元で動かしてみることでより深く理解できると思います。
よかったら試してみてくださいね。
それでわ!