まとめ
Laravelの.envではいくつかの文字列が特別扱いされて文字列ではない値に自動的に変換されます。機能としては前からあったようですが、公式ドキュメントにその記述が追加されたのは2018年3月末のこのコミットの模様。2018年4月2日現在では日本語版には反映されていません。
.envの記述 | env()ヘルパーの値 |
---|---|
true | (bool) true |
(true) | (bool) true |
false | (bool) false |
(false) | (bool) false |
empty | (string) '' |
(empty) | (string) '' |
null | (null) null |
(null) | (null) null |
ついでにこれら特別扱いされる文字列を変換させずにそのまま文字列として値が取れるように書きたければ、たとえば'true'なら以下のように書く必要があります。1
FOO="\"true\""
経緯
その値がboolであるような設定値を用意したいと思いました。仮にその名前を'app.my_flag', .envの中では'MY_FLAG'と書くつもりだったとします。プログラム中ではconfig('app.my_flag')でその値にアクセスできる感じ。
最初はこうしました。
.envに追加:
MY_FLAG=false
config/app.phpに追加:
'my_flag' => \App\MyHelper::env_bool('MY_FLAG'),
\App\MyHelper::env_bool
は自作のヘルパー関数です。
public static function env_bool($key, $default = false)
{
$result = env($key);
if (is_null($result)) {
return $default;
}
if ($result === 'true') {
return true;
}
if ($result === 'false') {
return false;
}
throw new \Exception(sprintf('invalid bool: key=%s, value=%s', $key, var_export($result, true)));
}
とりあえず動作確認でtinkerコマンドを打つといきなりエラーです。
% php artisan tinker
In MyHelper.php line 21:
invalid bool: key=MY_FLAG, value=true
ありゃー、なんでenv()がはじめからtrue
返すんだと思ってソース追っかけたら、こんな風になってたわけですよ。
if (! function_exists('env')) {
/**
* Gets the value of an environment variable.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
function env($key, $default = null)
{
$value = getenv($key);
if ($value === false) {
return value($default);
}
switch (strtolower($value)) {
case 'true':
case '(true)':
return true;
case 'false':
case '(false)':
return false;
case 'empty':
case '(empty)':
return '';
case 'null':
case '(null)':
return;
}
if (strlen($value) > 1 && Str::startsWith($value, '"') && Str::endsWith($value, '"')) {
return substr($value, 1, -1);
}
return $value;
}
}
知らんかったーと思ってヘルパー関数のマニュアルを確認したら初めに書いた記述にいきつきました。env_bool
なんてはじめから書く必要はなかったのです。しかしよくよく調べたらドキュメントの更新はつい3日前なのでこんなの知るわけがないですわな。間が悪いw
で””で囲まれてたらはがす処理もあるようなのでtrue
って文字列を書きたいときはとりあえず""で囲めばいいんじゃないかなという当たりを付けて、
.envに追加:
MY_STRING="true"
config/app.phpに追加:
'my_string' => env('MY_STRING'),
と準備して試してみましたがだめでした。
% php artisan tinker
Psy Shell v0.8.17 (PHP 7.2.4 — cli) by Justin Hileman
>>> config('app.my_string')
=> true
>>>
よくよくソースを読むと以下のような事情でした。
-
envヘルパーは
getenv()
で取った値の文字列が""で囲まれていたら、両端の""を削ります。(上記のとおり) -
.env
ファイルを読みこんで環境変数に設定する役割はphpdotenvパッケージの仕事ですが、これは""で囲まれた文字列は""をはがします。文字列に「"」を含めたければ「\」でエスケープする必要があります。
ということで""を剥がすひとがもう一人いたわけですね。
MY_STRING="\"true\""
とすることで、めでたくちゃんと取れるようになりました。
% php artisan tinker
Psy Shell v0.8.17 (PHP 7.2.4 — cli) by Justin Hileman
>>> config('app.my_string')
=> "true"
>>>
-
余談ですが、両端に「"」をもつ文字列を値としたいときは、
FOO="\"\"foo\"\""
のようにする必要があります。 ↩