2010-09-27 5 views
65

Je dois vérifier si la valeur est définie comme quoi que ce soit, y compris null. isset traite les valeurs null comme non définies et renvoie false. Prenez ce qui suit comme un exemple:Vérifiez si la valeur est isset et null

$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 satisfait aux exigences suivantes:

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

Toutes les idées?

+14

if (isset ($ foo)) // retourne false, je suis tombé sur la chaise, toutes ces années ... – max4ever

Répondre

63

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 
+0

+1 J'allais suggérer la même fonction, 'get_defined_vars' fait heureusement face à la portée. – salathe

+1

Semble fonctionner, mais j'espérais quelque chose de plus simple. Tant pis. Voyons voir si quelqu'un peut trouver un seul paquebot. –

+4

bien, vous n'avez pas besoin de vars, donc en théorie sa ligne "if (array_key_exists ('foo', get_defined_vars())) {}" – Hannes

0

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

+0

J'utilise is_null. Le résultat est le même quel que soit le 'isset'. –

+0

J'ai fait une erreur en postant ma première réponse: avez-vous essayé avec empty()? – Raveline

+0

Cela ne fonctionnera pas pour les valeurs qui ne sont pas vides et non NULL telles que FALSE, 0, array() ou "". – C9HDN

12

Voir Best way to test for a variable's existence in PHP; isset() is clearly broken

if(array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true 
if(array_key_exists('bar', $GLOBALS) && is_null($bar)) // false & => false 
+3

Le code que vous citez ne fonctionne que si la variable est dans la portée globale. – Raveline

+0

En effet mais n'est-ce pas le cas le plus fréquent? Dans une fonction, vous aurez des variables à portée globale et des arguments (qui sont toujours définis). Vous pouvez également avoir des propriétés d'objet, mais vous pouvez utiliser 'property_exists'. –

+0

L'utilisation de $ GLOBALS semble un peu volatile, je dois faire quelques tests moi-même avant de pouvoir déclarer que cela fonctionne. –

-2

is_null($bar) renvoie true, car il n'a pas de valeur du tout. Vous pouvez également utiliser:

if(isset($bar) && is_null($bar)) // returns false 

pour vérifier si $bar est défini et ne retourne vrai si:

$bar = null; 
if(isset($bar) && is_null($bar)) // returns true 
+0

Non, il a dit que 'if (isset ($ bar))' donne false quand '$ bar = null'. –

+0

ma mauvaise. mettra à jour ma réponse. – Ruel

+2

Ceci ne passera pas d'autres variables que null (par exemple si '$ bar =" test "'). –

0

Voici une solution stupide 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 
+1

Ne semble pas très portable .. :) –

+1

En effet. Et les performances peuvent également baisser. ;-) –

1

Le code suivant écrit que l'extension PHP est équivalente à array_key_exists ($ name, get_defined_vars()) (grâce à 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; 
    } 

} 
21

Si vous traitez avec des propriétés d'objet whcih pourraient 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() retourne TRUE même si la propriété a la valeur NULL.

+7

Vous pouvez faire la même chose pour les tableaux avec array_key_exists(); – C9HDN

2

J'ai trouvé que compact est une fonction qui ne tient pas compte des variables non définies, mais n'agit sur les mis à null, alors quand vous avez une grande table de symbole local j'imagine que vous pouvez obtenir une solution plus efficace sur le contrôle array_key_exists('foo', get_defined_vars()) par 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 
+0

Alternative intéressante. Mais notez qu'il est probablement plus lent que d'appeler array_key_exists sur un tableau existant, tel que $ GLOBALS - parce qu'une recherche dans une table de hachage ne devient pas plus lente, quand la table devient grande, et vous avez ajouté le travail supplémentaire de 'compact'. Néanmoins, je l'ai upvoted car il est utile dans une situation: si vous voulez savoir si 'foo' existe * dans le contexte actuel *, peu importe d'où il vient - si vous ne vous souciez pas de savoir si c'est local ou global, juste veux savoir si ça existe. – ToolmakerSteve

+0

@ToolmakerSteve - Je parlais en fait du coût potentiellement significatif de l'appel 'get_defined_vars'. Voir [ici] (http://stackoverflow.com/questions/27808704/what-is-the-performance-impact-off-get-defined-vars). – nzn

Questions connexes