/dev/null

脳みそのL1キャッシュ

PHP で未定義の定数は文字列として解釈されるよという話

動作環境

$ php -v
PHP 7.3.28 (cli) (built: Apr 29 2021 18:47:43) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.28, Copyright (c) 1998-2018 Zend Technologies
    with Xdebug v3.0.4, Copyright (c) 2002-2021, by Derick Rethans

本題

タイトル通り。今日の仕事中に出会った PHP の不思議動作です。

PHP では、$がついてない識別子は定数として解釈されます。更に、その定数が未定義の場合、識別子がそのまま文字列として解釈されます。

なので、下記のコードにおいて $msg には文字列 "helloworld" が格納されます。

<?php
$msg = hello . world;
echo $msg; /* "helloworld" */

また、文字列として解釈されるにはされますが、以下の warning が出力されます。 warning なので動作自体は停止しませんね。

<warning>PHP Warning:  Use of undefined constant hello - assumed 'hello' (this will throw an Error in a future version of PHP) in Psy Shell code on line 1</warning>
<warning>PHP Warning:  Use of undefined constant world - assumed 'world' (this will throw an Error in a future version of PHP) in Psy Shell code on line 1</warning>

このことについては、PHP のドキュメントの User Contributed Notes でも言及されています。

Lets expand comment of 'storm' about usage of undefined constants. His claim that 'An undefined constant evaluates as true...' is wrong and right at same time. As said further in documentation ' If you use an undefined constant, PHP assumes that you mean the name of the constant itself, just as if you called it as a string...'. So yeah, undefined global constant when accessed directly will be resolved as string equal to name of sought constant (as thought PHP supposes that programmer had forgot apostrophes and autofixes it) and non-zero non-empty string converts to True.

引用元: https://www.php.net/manual/ja/language.constants.php

この動作は一体誰得なんですかねぇ…

ちなみに、PHP8 では以下のように warning ではなく error になるようです。

Fatal error: Uncaught Error: Undefined constant "hello" in /tmp/15newekq82bbl0/tester.php:3 Stack trace: #0 {main} thrown in /tmp/15newekq82bbl0/tester.php on line 3