値がnullを含む何かとして定義されているかどうかを確認する必要があります。 isset
は、null値を未定義として扱い、false
を返します。例として次のことを考えてください。
$foo = null;
if(isset($foo)) // returns false
if(isset($bar)) // returns false
if(isset($foo) || is_null($foo)) // returns true
if(isset($bar) || is_null($bar)) // returns true, raises a notice
ご了承ください $bar
は未定義です。
次の条件を満たす条件を見つける必要があります。
if(something($bar)) // returns false;
if(something($foo)) // returns true;
何か案は?
IIRCでは、このために get_defined_vars()
を使用できます。
$foo = NULL;
$vars = get_defined_vars();
if (array_key_exists('bar', $vars)) {}; // Should evaluate to FALSE
if (array_key_exists('foo', $vars)) {}; // Should evaluate to TRUE
NULLの値を持つ可能性のあるオブジェクトプロパティを処理する場合は、property_exists()
の代わりに isset()
を使用できます。
<?php
class myClass {
public $mine;
private $xpto;
static protected $test;
function test() {
var_dump(property_exists($this, 'xpto')); //true
}
}
var_dump(property_exists('myClass', 'mine')); //true
var_dump(property_exists(new myClass, 'mine')); //true
var_dump(property_exists('myClass', 'xpto')); //true, as of PHP 5.3.0
var_dump(property_exists('myClass', 'bar')); //false
var_dump(property_exists('myClass', 'test')); //true, as of PHP 5.3.0
myClass::test();
?>
Isset()とは対照的に、property_exists()は、プロパティの値がNULLであってもTRUEを返します。
PHPで変数の存在をテストする最良の方法。isset()は明らかに壊れています
if( array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true
if( array_key_exists('bar', $GLOBALS) && is_null($bar)) // false & => false
compact
は未設定の変数を無視するが、null
に設定された変数に作用する関数であることがわかったので、大きなローカルシンボルテーブルがある場合、より効率的なソリューションが得られると思いますarray_key_exists('foo', get_defined_vars())
を使用してarray_key_exists('foo', compact('foo'))
をチェックする:
$foo = null;
echo isset($foo) ? 'true' : 'false'; // false
echo array_key_exists('foo', compact('foo')) ? 'true' : 'false'; // true
echo isset($bar) ? 'true' : 'false'; // false
echo array_key_exists('bar', compact('bar')) ? 'true' : 'false'; // false
更新
PHP 7.3 compact() の時点で、値が設定されていないことを通知するため、残念ながらこの選択肢は無効になりました。
compact()は、指定された文字列が未設定の変数を参照している場合、E_NOTICEレベルのエラーを発行するようになりました。以前は、このような文字列は静かにスキップされていました。
PHP拡張機能はarray_key_exists($ name、get_defined_vars())と同等です(HenrikとHannesに感謝します)。
// get_defined_vars()
// https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions.c#L1777
// array_key_exists
// https://github.com/php/php-src/blob/master/ext/standard/array.c#L4393
PHP_FUNCTION(is_defined_var)
{
char *name;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
if (zend_symtable_exists(EG(active_symbol_table), name, name_len + 1)) {
RETURN_TRUE;
}
}
ここで、xdebugを使用したばかげた回避策がいくつかあります。 ;-)
function is_declared($name) {
ob_start();
xdebug_debug_zval($name);
$content = ob_get_clean();
return !empty($content);
}
$foo = null;
var_dump(is_declared('foo')); // -> true
$bla = 'bla';
var_dump(is_declared('bla')); // -> true
var_dump(is_declared('bar')); // -> false