🈚️

Laravel で null ドライバを .env から指定するときは "'null'" と書こう

2021/03/15に公開

タイトルがすべてですが、例えばログ設定で 'null' チャンネル [1] を使いたいときはこう書きましょう

.env
LOG_CHANNEL="'null'"
# or
LOG_CHANNEL='"null"'

なんで?

env() ヘルパーが .env に書かれている文字列の nullNULL 値として解釈してしまうからです

実際に .env を以下のように書いて [2]

.env
LOG_CHANNEL=null

env() ヘルパーの挙動を確かめると

>>> var_dump(getenv('LOG_CHANNEL'))
string(4) "null"
>>> var_dump(env('LOG_CHANNEL'))
NULL

NULL 値が返ってきます

config/logging.php'null' チャンネルを利用した際はログの出力が一切ないことを期待していますが、
この状態でログ出力を実際に試すと emergency logger が利用され、 storage/logs/laravel.log にログが出力されてしまいます

storage/logs/laravel.log
[2021-03-14 15:46:10] laravel.EMERGENCY: Unable to create configured logger. Using emergency logger. {"exception":"[object] (InvalidArgumentException(code: 0): Log [] is not defined. at /var/www/html/vendor/laravel/framework/src/Illuminate/Log/LogManager.php:192)
[stacktrace]
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Log/LogManager.php(118): Illuminate\\Log\\LogManager->resolve()
#1 /var/www/html/vendor/laravel/framework/src/Illuminate/Log/LogManager.php(98): Illuminate\\Log\\LogManager->get()
#2 /var/www/html/vendor/laravel/framework/src/Illuminate/Log/LogManager.php(608): Illuminate\\Log\\LogManager->driver()
#3 /var/www/html/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(261): Illuminate\\Log\\LogManager->debug()
...(snip)...
[2021-03-14 15:46:10] laravel.DEBUG: hoge  

"'null'" にするとどうなるの?

環境変数は string(6) "'null'" として解釈されますが、 env() ヘルパーは string(4) "null" を返します

>>> var_dump(getenv('LOG_CHANNEL'))
string(6) "'null'"
>>> var_dump(env('LOG_CHANNEL'))
string(4) "null"

これは env() ヘルパーの実装がよしなにやってくれているからです
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Env.php#L93-L95

これで 'null' チャンネルが正しく使われて、ログがどこにも出力されなくなります

>>> Log::debug('hoge')
=> null
>>> # どこにもログが出力されない

ログの 'null' チャンネルっていつ使うの?

テスト実行時など、ログを出したくないときに便利です

'null' 以外のドライバ名にしないの?

  • ログの 'null' チャンネル名は当初 'none' としてプロポーザルが出されていました [3]
  • 最終的に、 null ドライバなんだから null という名前をつけたほうが一貫性があって良い、で落ち着いたようです [4]
  • この手の問題は、将来的に null を残しつつ別名もサポートしたほうが便利だね、という話も出ていましたが、まだ実現はしていないようです [5]

参考

脚注
  1. ログの 'null' チャネルは 6.2.0 で追加されました ↩︎

  2. LOG_CHANNEL='null'LOG_CHANNEL="null" も同様 ↩︎

  3. https://github.com/laravel/ideas/issues/1806 ↩︎

  4. https://github.com/laravel/laravel/pull/5106#issuecomment-531220153 ↩︎

  5. https://github.com/laravel/framework/pull/27691#issuecomment-467872248 ↩︎

Discussion