web-dev-qa-db-fra.com

Vérifier si la valeur est définie et nulle

J'ai besoin de vérifier si la valeur est définie comme quoi que ce soit, y compris null. isset traite les valeurs nulles comme non définies et renvoie false. Prenons l'exemple suivant:

$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

Notez que $bar n'est pas défini.

Je dois trouver une condition qui remplit les conditions suivantes:

if(something($bar)) // returns false;
if(something($foo)) // returns true;

Des idées?

81
Tatu Ulmanen

IIRC, vous pouvez utiliser get_defined_vars() pour cela:

$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
78
Henrik Opel

Si vous avez affaire à des propriétés d'objet qui peuvent avoir une valeur NULL, vous pouvez utiliser: property_exists() au lieu de 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();

?>

Contrairement à isset (), property_exists () renvoie TRUE même si la propriété a la valeur NULL.

25
John Magnolia

Voir Meilleure façon de tester l'existence d'une variable en PHP; isset () est clairement cassé

 if( array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true
 if( array_key_exists('bar', $GLOBALS) && is_null($bar)) // false &  => false
13
Loïc Février

J'ai constaté que compact est une fonction qui ignore les variables non définies mais agit sur celles définies sur null, donc lorsque vous avez une grande table de symboles locale, j'imagine que vous pouvez obtenir une solution plus efficace sur la vérification de array_key_exists('foo', get_defined_vars()) en utilisant 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

Mise à jour

À partir de PHP 7.3 compact () donnera un avis pour les valeurs non définies, donc malheureusement cette alternative n'est plus valide.

compact () émet désormais une erreur de niveau E_NOTICE si une chaîne donnée fait référence à une variable non définie. Auparavant, ces chaînes étaient silencieusement ignorées.

3
nzn

Le code suivant écrit sous la forme PHP est équivalente à array_key_exists ($ name, get_defined_vars ()) (merci à Henrik et 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;
    }

}
1
masakielastic

Vous pouvez utiliser is_null et empty au lieu de isset (). Vide n'imprime pas de message d'erreur si la variable n'existe pas.

0
Raveline

Voici une solution de contournement stupide en utilisant 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
0
Philippe Gerber