La meilleure façon de tester L'existence D'une variable en PHP; isset () est clairement cassé

De la isset() docs :

isset() will return FALSE if testing a variable that has been set to NULL.

en gros, isset() ne vérifie pas si la variable est définie du tout, mais si elle est définie à autre chose que NULL .

étant Donné que, quelle est la meilleure façon de vérifier l'existence d'une variable? J'ai essayé quelque chose comme:

if(isset($v) || @is_null($v))

(le @ est nécessaire pour éviter l'avertissement $v n'est pas défini) mais is_null() a un problème similaire à isset() : il retourne TRUE sur les variables non activées! Il apparaît également que:

@($v === NULL)

fonctionne exactement comme @is_null($v) , donc c'est hors de question, aussi.

comment sommes-nous censés vérifier de manière fiable L'existence d'une variable en PHP?


Edit: il y a clairement une différence en PHP entre les variables qui ne sont pas définies, et les variables qui sont définies à NULL :

<?php
$a = array('b' => NULL);
var_dump($a);

PHP montre que $a['b'] existe, et a une valeur NULL . Si vous ajoutez:

var_dump(isset($a['b']));
var_dump(isset($a['c']));

vous pouvez voir l'ambiguïté dont je parle avec la fonction isset() . Voici la sortie de ces trois var_dump()s :

array(1) {
  ["b"]=>
  NULL
}
bool(false)
bool(false)

éditer de nouveau: deux choses.

un, un étui. Un tableau étant transformé en données D'une déclaration SQL UPDATE , où les clés du tableau sont les colonnes de la table, et les valeurs du tableau sont les valeurs à appliquer à chaque colonne. N'importe laquelle des colonnes de la table peut contenir une valeur NULL , signifiée en passant une valeur NULL dans le tableau. Vous avez besoin de une façon de différencier une clé de tableau non existante, et la valeur d'un tableau étant définie à NULL ; c'est la différence entre Ne pas mettre à jour la valeur de la colonne et mise à jour de la valeur de la colonne en NULL .

le Second, Zoredache la réponse de , array_key_exists() fonctionne correctement, pour mon ci-dessus, ainsi que pour toutes les variables globales:

<?php
$a = NULL;
var_dump(array_key_exists('a', $GLOBALS));
var_dump(array_key_exists('b', $GLOBALS));

sorties:

bool(true)
bool(false)

puisque cela fonctionne correctement presque partout, je peux voir qu'il y a une ambiguïté entre les variables qui n'existent pas et les variables qui sont définies à NULL , j'appelle array_key_exists() la manière officielle la plus facile en PHP De vraiment vérifier l'existence d'une variable .

(seul autre cas je peux penser est pour les propriétés de classe, pour lequel il ya property_exists() , qui, selon ses docs , fonctionne de la même façon que array_key_exists() en ce qu'il distingue correctement entre Ne pas être mis et être mis à NULL .)

177
demandé sur Community 2009-01-06 23:46:50

17 réponses

si la variable que vous vérifiez se trouve dans la portée globale vous pouvez faire:

array_key_exists('v', $GLOBALS) 
92
répondu Zoredache 2014-04-24 22:11:54

tentative de donner un aperçu des diverses discussions et réponses:

il n'y a pas de réponse unique à la question qui puisse remplacer toutes les façons d'utiliser isset . certains cas d'utilisation sont traités par d'autres fonctions, tandis que d'autres ne résistent pas à un examen minutieux, ou ont une valeur douteuse au-delà du golf code. Loin d'être "cassée" ou "incohérente", d'autres cas d'utilisation démontrent pourquoi la réaction de isset à null est comportement logique.

cas D'utilisation réelle (avec solutions)

1. Tableau keys

Les tableaux

peuvent être traités comme des collections de variables, avec unset et isset les traitant comme s'ils étaient. Cependant, comme elles peuvent être itérées, comptées, etc., une valeur manquante n'est pas la même que celle d'une valeur null .

la réponse dans ce cas, est à utiliser array_key_exists() au lieu de isset() .

Puisqu'il s'agit de vérifier le tableau en tant qu'argument de fonction, PHP élèvera quand même" notices " si le tableau lui-même n'existe pas. Dans certains cas, on peut valablement soutenir que chaque dimension aurait dû être initialisée en premier, de sorte que l'Avis fait son travail. Pour d'autres cas, une fonction" récursive " array_key_exists , qui vérifiait chaque dimension du tableau à son tour, éviterait cela, mais être le même que le @array_key_exists . Il est aussi quelque peu tangent à la manipulation des valeurs null .

2. Propriétés de l'objet

dans la théorie traditionnelle de la "programmation orientée objet", l'encapsulation et le polymorphisme sont des propriétés clés des objets; dans une implémentation OOP basée sur une classe comme PHP, les propriétés encapsulées sont déclarées comme faisant partie de la définition de classe, et des niveaux d'accès donnés ( public , protected , ou private ).

cependant, PHP vous permet également d'ajouter dynamiquement des propriétés à un objet, comme vous le feriez pour les clés d'un tableau, et certaines personnes utilisent des objets sans classe (techniquement , des instances de l'construit dans stdClass , qui n'a aucune méthode ou fonctionnalité privée) d'une manière similaire aux tableaux associatifs. Cela conduit à des situations où une fonction voudrez peut-être savoir si une propriété particulière a été ajoutée à l'objet donné.

comme avec les clés de tableau, une solution pour vérifier les propriétés de l'objet est inclus dans le langage, appelé, assez raisonnablement, property_exists .

Non-justifiable en cas d'utilisation, avec un débat

3. register_globals , et autres polluants de l'espace géographique

la caractéristique register_globals a ajouté des variables à la portée globale dont les noms ont été déterminés par des aspects de la requête HTTP (GET et POST, les paramètres et les cookies). Cela peut conduire à code buggy et non sûr, c'est pourquoi il a été désactivé par défaut depuis PHP 4.2, publié en août 2000 et complètement supprimé dans PHP 5.4, publié en mars 2012 . Cependant, il est possible que certains systèmes fonctionnent encore avec cette fonctionnalité activée ou émulée. Il est également possible de "polluer" l'espace de noms global d'une autre manière, en utilisant le mot-clé global ou le tableau $GLOBALS .

tout d'abord, register_globals lui-même est peu susceptible de produire de manière inattendue une variable null , puisque les valeurs GET, POST et cookie seront toujours des chaînes (avec '' retournant toujours true de isset ), et les variables de la session doivent être entièrement sous le contrôle du programmeur.

Deuxièmement, la pollution d'une variable avec la valeur null est seulement un problème si cela sur-écrit quelque initialisation précédente. "Surécrire "une variable non initialisée avec null ne serait problématique que si le code autre part distinguait entre les deux états, donc à lui seul cette possibilité est un argument contre faisant une telle distinction.

4. get_defined_vars et compact

quelques fonctions rarement utilisées en PHP, telles que get_defined_vars et compact , vous permettent de traiter les noms de variables comme si elles étaient des clés dans un tableau. Pour les variables globales, le super-tableau global $GLOBALS permet un accès similaire, et est plus fréquente. Ces méthodes d'accès va se comporter différemment si une variable n'est pas définie dans le champ pertinent.

une fois que vous avez décidé de traiter un ensemble de variables comme un tableau en utilisant l'un de ces mécanismes, vous pouvez faire toutes les mêmes opérations que sur n'importe quel Tableau normal. Par conséquent, voir 1.

fonctionnalité qui n'existait que pour prédire comment ces fonctions sont sur le point de se comporter (par exemple "y aura-t-il une clé 'foo' dans le tableau retourné par get_defined_vars ?") est superflu, puisque vous pouvez simplement exécuter la fonction et de découvrir sans effets néfastes.

4a. Variables variables ( $$foo )

bien que pas tout à fait la même chose que les fonctions qui transforment un ensemble de variables en un tableau associatif, la plupart cas à l'aide de "les variables" ("affecter à une variable nommée basé sur cette autre variable") peut et doit être modifié pour utiliser un tableau associatif à la place.

un nom de variable, fondamentalement, est l'étiquette donnée à une valeur par le programmeur; si vous la déterminez à l'exécution, ce n'est pas vraiment une étiquette mais une clé dans un magasin de valeur de clé. Plus concrètement, en n'utilisant pas un tableau, vous perdez la capacité de compter, itérer, etc; il peut aussi devient impossible d'avoir une variable" à l'extérieur "de la mémoire de valeur de la clé, car il pourrait être sur-Écrit par $$foo .

une fois modifié pour utiliser un tableau associatif, le code se soumettra à la solution 1. L'accès Indirect à la propriété de l'objet (par exemple $foo->$property_name ) peut être abordé avec la solution 2.

5. isset est tellement plus facile à taper que array_key_exists

Je ne suis pas sûr que ce soit vraiment pertinent, mais oui, les noms de fonction peuvent être assez longs et incohérents parfois. Apparemment, les versions pré-historiques de PHP ont utilisé la longueur d'un nom de fonction comme une clé de hachage, donc Rasmus délibérément inventé des noms de fonction comme htmlspecialchars de sorte qu'ils auraient un nombre inhabituel de caractères...

toujours, au moins on n'écrit pas Java, hein? ;)

6. Les variables non initialisées ont un type

Le page de manuel sur la variable bases inclut cette déclaration:

les variables non initialisées ont une valeur par défaut de leur type en fonction du contexte dans lequel elles sont utilisées

Je ne suis pas sûr qu'il y ait quelque notion dans le moteur Zend de" uninitialized but known type " ou si c'est trop de lecture dans la déclaration.

ce qui est clair, c'est qu'il n'y a aucune différence pratique dans leur comportement, puisque les comportements décrits sur cette page pour les variables non initialisées sont identiques au comportement d'une variable dont la valeur est null . Pour prendre un exemple, à la fois $a et $b dans ce code se terminera comme l'entier 42 :

unset($a);
$a += 42;

$b = null;
$b += 42;

(le premier lancera un avis sur une variable non déclarée, dans une tentative de vous faire écrire un meilleur code, mais il ne fera aucune différence à la façon dont le code fonctionne réellement.)

99. Détecter si une fonction a exécuter

(en Gardant cette dernière, car il est beaucoup plus longue que les autres. Peut-être que je l'éditerai plus tard...)

considérons le code suivant:

$test_value = 'hello';
foreach ( $list_of_things as $thing ) {
    if ( some_test($thing, $test_value) ) {
        $result = some_function($thing);
    }
}
if ( isset($result) ) {
    echo 'The test passed at least once!';
}

si some_function peut retourner null , il y a une possibilité que le echo ne sera pas atteint même si some_test retourné true . L'intention du programmeur était de détecter quand $result n'a jamais été défini, mais PHP ne leur permet pas de le faire.

cependant, il y a d'autres problèmes avec cette approche, qui deviennent clairs si vous ajoutez une boucle extérieure:

foreach ( $list_of_tests as $test_value ) {
    // something's missing here...
    foreach ( $list_of_things as $thing ) {
        if ( some_test($thing, $test_value) ) {
            $result = some_function($thing);
        }
    }
    if ( isset($result) ) {
        echo 'The test passed at least once!';
    }
}

parce que $result n'est jamais initialisé explicitement, il prendra une valeur lorsque le tout premier test passe, ce qui rend impossible de dire si les tests ultérieurs ont réussi ou non. il s'agit en fait d'un bug extrêmement commun lorsque les variables ne sont pas initialisées correctement.

pour corriger cela, nous devons faire quelque chose sur la ligne où j'ai dit que quelque chose manquait. La solution la plus évidente est de fixer $result à une "valeur finale" que some_function ne pourra jamais retourner; si c'est null , alors le reste du code fonctionnera très bien. S'il n'y a pas de candidat naturel pour une valeur finale parce que some_function a un type de retour extrêmement imprévisible (ce qui est probablement mauvais signe en soi), puis une valeur booléenne supplémentaire , par exemple $found , pourrait être utilisée à la place.

première expérience de pensée: la very_null constante

PHP pourrait théoriquement fournir une constante spéciale - ainsi que null - pour une utilisation comme valeur terminale ici; probablement, il serait illégal de retourner ceci d'une fonction, ou il serait forcé à null , et la même chose s'appliquerait probablement à le passer en tant que fonction argument. Cela rendrait ce cas très spécifique légèrement plus simple, mais dès que vous avez décidé de re-factoriser le code - par exemple, pour mettre la boucle interne dans une fonction séparée - il deviendrait inutile. Si la constante pouvait être transmise d'une fonction à l'autre, vous ne pouviez pas garantir que some_function ne la retournerait pas, de sorte qu'elle ne serait plus utile en tant que valeur terminale universelle.

l'argument pour détecter des variables non initialisées dans ce cas se résume à la argument pour cette constante spéciale: si vous remplacez le Commentaire par unset($result) , et traitez cela différemment de $result = null , vous introduisez une "valeur" pour $result qui ne peut pas être transmise, et ne peut être détecté par des fonctions spécifiques intégrées.

expérience de Pensée de deux: affectation compteur

une autre façon de penser à ce que le dernier if demande est "Est-ce que quelque chose a fait une cession à $result ?" Plutôt que de considérer qu'il s'agit d'une valeur spéciale de $result , vous pourriez peut-être penser à cela comme "metadata" environ la variable, un peu comme "tainting variable"de Perl. Ainsi, plutôt que isset , on pourrait l'appeler has_been_assigned_to , et plutôt que unset , reset_assignment_state .

Mais si oui, pourquoi s'arrêter à un booléen? Si vous voulez savoir combien de fois le critère adopté; il vous suffit d'étendre vos métadonnées pour un entier et ont get_assignment_count et reset_assignment_count ...

de toute évidence, l'ajout d'une telle caractéristique aurait un compromis quant à la complexité et à la performance du langage, de sorte qu'il devrait être soigneusement pesé par rapport à son utilité prévue. Comme dans le cas d'une constante very_null , elle ne serait utile que dans des circonstances très étroites et résisterait de la même façon à la reconfiguration.

la question, si tout va bien, est de savoir pourquoi le moteur PHP devrait assumer à l'avance que vous souhaitez garder une trace de ces choses, plutôt que de vous laisser faire explicitement, à l'aide de code.

42
répondu IMSoP 2013-09-05 21:52:07

Parfois je me perds un peu en essayant de comprendre quelle opération de comparaison utiliser dans une situation donnée. isset() s'applique uniquement aux valeurs non initialisées ou explicitement nulles. Passer / assigner null est un excellent moyen de s'assurer qu'une comparaison logique fonctionne comme prévu.

pourtant, il est un peu difficile de penser, alors voici une matrice simple comparant comment différentes valeurs seront évaluées par différentes opérations:

|           | ===null | is_null | isset | empty | if/else | ternary | count>0 |
| -----     | -----   | -----   | ----- | ----- | -----   | -----   | -----   |
| $a;       | true    | true    |       | true  |         |         |         |
| null      | true    | true    |       | true  |         |         |         |
| []        |         |         | true  | true  |         |         |         |
| 0         |         |         | true  | true  |         |         | true    |
| ""        |         |         | true  | true  |         |         | true    |
| 1         |         |         | true  |       | true    | true    | true    |
| -1        |         |         | true  |       | true    | true    | true    |
| " "       |         |         | true  |       | true    | true    | true    |
| "str"     |         |         | true  |       | true    | true    | true    |
| [0,1]     |         |         | true  |       | true    | true    | true    |
| new Class |         |         | true  |       | true    | true    | true    |

pour ajuster la table I compressé les étiquettes un peu:

  • $a; se rapporte à une variable déclarée mais non assignée
  • tout le reste dans la première colonne se réfère à une valeur assignée, comme:
    • $a = null;
    • $a = [];
    • $a = 0;
    • ...
  • les colonnes se réfèrent à les opérations de comparaison, comme:
    • $a === null
    • isset($a)
    • empty($a)
    • $a ? true : false
    • ...

tous les résultats sont booléens, true est imprimé et false est omis.

vous pouvez exécuter les tests vous-même, vérifiez ce gist:

https://gist.github.com/mfdj/8165967

21
répondu Mark Fox 2014-08-07 22:09:56

vous pouvez utiliser la construction de langage compacte pour tester l'existence d'une variable nulle. Les Variables qui n'existent pas n'apparaîtra pas dans le résultat, tandis que des valeurs null spectacle.

$x = null;
$y = 'y';

$r = compact('x', 'y', 'z');
print_r($r);

// Output:
// Array ( 
//  [x] => 
//  [y] => y 
// ) 

Dans le cas de votre exemple:

if (compact('v')) {
   // True if $v exists, even when null. 
   // False on var $v; without assignment and when $v does not exist.
}

bien sûr pour les variables de portée globale vous pouvez aussi utiliser array_key_exists().

B. T. w. personnellement, j'éviterais des situations comme la peste où il y a une sémantique différence entre une variable inexistante et la variable ayant une valeur nulle. PHP et la plupart des autres langues ne pensent tout simplement pas qu'il existe.

17
répondu Matijs 2009-12-28 11:57:53

expliquer NULL, pensée logique

je suppose que la réponse évidente à tous c'est... N'initialisez pas vos variables comme NULL, initalisez-les comme quelque chose de pertinent à ce qu'elles sont censées devenir.

Traiter NULL correctement

NULL doit être considéré comme "valeur non existante", ce qui est le sens de NULL. La variable ne peut pas être classée comme existant à PHP parce QU'on ne lui a pas dit quel type d'entité elle est en essayant d'être. Il se peut qu'il n'existe pas, alors PHP dit simplement "bien, il n'en a pas parce qu'il n'y a pas de raison à cela de toute façon et nul est ma façon de le dire".

un argument

discutons maintenant. "Mais nul est comme dire 0 ou faux ou ".

Wrong, 0-FALSE-" sont toujours classés comme des valeurs vides, mais ils sont spécifiés comme un type de valeur ou réponse prédéterminée à une question. FALSE la réponse est oui ou non, " la réponse est dans le titre quelqu'un de soumis, et 0 est la réponse à la quantité ou le temps, etc. Ils sont définis comme un type de réponse/résultat qui les rend valides comme étant définis.

NULL est juste pas de réponse quoi que ce soit, il ne nous dit pas oui ou non et il ne nous dit pas l'heure et il ne nous dit pas qu'une chaîne Vierge a été soumise. C'est la logique de base pour comprendre NULL.

résumé

il ne s'agit pas de créer des fonctions farfelues pour contourner le problème, il s'agit juste de changer la façon dont votre cerveau regarde NULL. Si elle est nulle, supposons qu'elle n'est pas définie comme quoi que ce soit. Si vous définissez des variables à l'avance, définissez-les comme 0, FALSE ou "" selon le type d'utilisation que vous prévoyez pour elles.

n'hésitez pas à citer ceci. C'est en haut de ma logique de la tête :)

15
répondu greatbigmassive 2010-03-31 10:25:21

les propriétés des objets peuvent être vérifiées par property_exists

exemple tiré d'un essai unitaire:

function testPropertiesExist()
{
    $sl =& $this->system_log;
    $props = array('log_id',
                   'type',
                   'message',
                   'username',
                   'ip_address',
                   'date_added');

    foreach($props as $prop) {
        $this->assertTrue(property_exists($sl, $prop),
                           "Property <{$prop}> exists");
    }
}
9
répondu 2009-01-24 12:35:01

comme ajout à discussion de greatbigmassive sur ce que nul signifie , considérez ce que" l'existence d'une variable " signifie réellement.

dans de nombreuses langues, vous devez déclarer explicitement chaque variable avant de l'utiliser ; cela peut déterminer son type, mais plus important encore, il déclare son portée . Une variable "existe" partout dans sa portée, et nulle part en dehors d'elle - que ce soit un ensemble une fonction, ou d'un seul "bloc".

dans son champ d'application, une variable attribue une signification à une étiquette que vous, le programmeur, avez choisie. En dehors de son champ d'application, cette étiquette n'a pas de sens (que vous utilisiez la même étiquette dans un champ d'application différent est fondamentalement hors de propos).

en PHP, les variables n'ont pas besoin d'être déclarées - elles prennent vie dès que vous en avez besoin. Lorsque vous écrivez à une variable pour pour la première fois, PHP attribue une entrée en mémoire pour cette variable. Si vous lisez à partir d'une variable qui n'a pas actuellement d'entrée, PHP considère que cette variable a la valeur NULL .

cependant, les détecteurs automatiques de qualité de code vous avertiront généralement si vous utilisez une variable sans "l'initialiser" en premier. Tout d'abord, cela aide à détecter les fautes de frappe, comme l'affectation à $thingId mais la lecture de $thing_id ; mais, deuxièmement, il vous oblige à considérer la portée plus que cette variable a un sens, comme une déclaration le ferait.

tout code qui se soucie de savoir si une variable "existe" fait partie du champ d'application de cette variable - qu'il ait été initialisé ou non, vous en tant que programmeur avez donné cette étiquette signification à ce point du code. Puisque vous l'utilisez, il doit dans un certain sens "exister", et s'il existe, il doit avoir une valeur implicite; en PHP, cette valeur implicite est null .

en raison de la façon dont PHP fonctionne, il est possible d'écrire du code qui traite l'espace de noms des variables existantes non pas comme une portée d'étiquettes que vous avez donné un sens, mais comme une sorte de stockage de valeurs clés. Vous pouvez, par exemple, exécuter le code comme ceci: $var = $_GET['var_name']; $$var = $_GET['var_value']; . ce n'est pas parce que tu peux que c'est une bonne idée.

il s'avère que PHP a une bien meilleure façon de représenter les magasins de valeurs clés, appelés tableaux associatifs. Et bien que la valeurs d'un tableau peuvent être traités comme des variables, vous pouvez également effectuer des opérations sur le tableau dans son ensemble. si vous avez un tableau associatif, vous pouvez tester s'il contient une clé en utilisant array_key_exists() .

vous pouvez également utiliser des objets d'une manière similaire, en définissant dynamiquement les propriétés, dans ce cas vous pouvez utiliser property_exists() exactement de la même manière. Bien sûr, si vous définissez une classe, vous pouvez déclarer quelles propriétés il a - vous pouvez même choisir entre public , private , et protected portée.

bien qu'il y ait une différence technique entre une variable (par opposition à une clé de tableau, ou une propriété d'objet) qui n'a pas été initialisée (ou qui a été explicitement unset() ) et une variable dont la valeur est null , tout code qui considère cette différence comme significative utilise des variables d'une manière qu'elles ne sont pas destinées à être utilisées.

4
répondu IMSoP 2017-05-23 12:17:54

isset vérifie si la variable est définie et, dans l'affirmative, si sa valeur n'est pas nulle. Cette dernière partie n'entre pas (à mon avis) dans le cadre de cette fonction. Il n'y a pas de travail décent pour déterminer si une variable est nulle parce qu'elle n'est pas définie ou parce que elle est explicitement définie à nul .

Voici une solution possible:

$e1 = error_get_last();
$isNULL = is_null(@$x);
$e2 = error_get_last();
$isNOTSET = $e1 != $e2;
echo sprintf("isNOTSET: %d, isNULL: %d", $isNOTSET, $isNULL);

// Sample output:
// when $x is not set: isNOTSET: 1, isNULL: 1
// when $x = NULL:     isNOTSET: 0, isNULL: 1
// when $x = false:    isNOTSET: 0, isNULL: 0

autre contournement est de sonder la sortie de get_defined_vars() :

$vars = get_defined_vars();
$isNOTSET = !array_key_exists("x", $vars);
$isNULL = $isNOTSET ? true : is_null($x);
echo sprintf("isNOTSET: %d, isNULL: %d", $isNOTSET, $isNULL);

// Sample output:
// when $x is not set: isNOTSET: 1, isNULL: 1
// when $x = NULL:     isNOTSET: 0, isNULL: 1
// when $x = false:    isNOTSET: 0, isNULL: 0
3
répondu Salman A 2017-01-15 09:41:26

Je ne suis pas d'accord avec votre raisonnement à propos de NULL , et dire que vous devez changer votre état d'esprit à propos de NULL est juste bizarre.

je pense que isset() n'a pas été conçu correctement, isset() devrait vous dire si la variable a été définie et il ne devrait pas être concerné par la valeur réelle de la variable.

Que faire si vous vérifiez les valeurs retournées à partir d'une base de données et que l'une des colonnes a une valeur nulle, vous voulez toujours sachez si elle existe même si la valeur est nulle...non ne faites pas confiance à isset() ici.

de même

$a = array ('test' => 1, 'hello' => NULL);

var_dump(isset($a['test']));   // TRUE
var_dump(isset($a['foo']));    // FALSE
var_dump(isset($a['hello']));  // FALSE

isset () aurait dû être conçu pour fonctionner comme ceci:

if(isset($var) && $var===NULL){....

de cette façon nous laissons au programmeur le soin de vérifier les types et de ne pas le laisser à isset() de supposer qu'il n'est pas là parce que la valeur est nulle - son design juste stupide

2
répondu Christof Coetzee 2011-01-28 15:48:40

je vais ajouter deux cents à ça. L'une des raisons pour lesquelles cette question prête à confusion est que ce scénario semble donner le même résultat que la déclaration des erreurs et non au complet:

$a = null;
var_dump($a); // NULL
var_dump($b); // NULL

vous pourriez supposer à partir de ce résultat que la différence entre $a = null et ne pas définir $b du tout est rien.

Manivelle rapport d'erreur:

NULL

Notice: Undefined variable: b in xxx on line n
NULL

Note: il a lancé une erreur variable non définie, mais la valeur de sortie de var_dump est toujours NULL .

PHP a évidemment une capacité interne de distinguer entre une variable nulle et une variable non définie. Il me semble qu'il devrait y avoir une fonction intégrée pour le vérifier.

je pense que la réponse acceptée est bonne pour la plupart, mais si je devais le mettre en œuvre, j'écrirais un papier d'emballage. Comme mentionné précédemment, dans cette réponse , je dois admettre que je n'ai pas réellement rencontré une situation où cela a été un problème. J'semblent presque toujours dans un scénario où mes variables sont définies, ou ils ne le sont pas (défini, indéfini, null, blanc, etc). Je ne veux pas dire qu'une telle situation ne se reproduira pas à l'avenir, mais comme il semble être tout à fait un problème unique, Je ne suis pas surpris que les développeurs PHP n'ont pas pris la peine de mettre cela en.

2
répondu Robbie Averill 2017-05-23 12:26:05

si j'exécute ce qui suit:

echo '<?php echo $foo; ?>' | php

j'obtiens une erreur:

PHP Notice:  Undefined variable: foo in /home/altern8/- on line 1

si j'exécute ce qui suit:

echo '<?php if ( isset($foo) ) { echo $foo; } ?>' | php

Je ne comprends pas l'erreur.

si j'ai une variable qui devrait être définie, je fais habituellement quelque chose comme ce qui suit.

$foo = isset($foo) ? $foo : null;

ou

if ( ! isset($foo) ) $foo = null;

de cette façon, plus tard dans le script, je peux utiliser $foo et savoir qu'il "is set", et qu'il est par défaut null. Plus tard, je peux if ( is_null($foo) ) { /* ... */ } si j'ai besoin de savoir avec certitude que la variable existe, même si elle est nulle.

Le plein isset documentation , lit-un peu plus que ce qui était initialement collé. Oui, il retourne false pour une variable qui était précédemment définie mais qui est maintenant nulle, mais il retourne également false si une variable n'a pas encore été définie (jamais) et pour toute variable qui a été marquée comme unset. Il note également que le octet nul ("\0") n'est pas considéré nul et retournera true.

Déterminer si une variable est définie.

si une variable a été désactivée avec la fonction unset(), il n'est plus fixé. isset () retournera FALSE si un test variable qui a été définie à NULL. Notez aussi qu'un octet nul ("\0") est pas équivalent à la valeur PHP NULL constant.

1
répondu Beau Simensen 2009-01-06 21:17:00

essayer d'utiliser

unset($v)

il semble que le seul moment où une variable n'est pas définie est quand elle est spécifiquement désactivée($v). Il semble que votre sens de 'existence' soit différent de la définition de PHP. NULL existe certainement, il est NULL.

1
répondu Joe Phillips 2009-01-06 22:22:47

je dois dire que dans toutes mes années de programmation PHP, Je n'ai jamais rencontré de problème avec isset() retourner false sur une variable nulle. OTOH, j'ai rencontré des problèmes avec isset() échouant sur une entrée de tableau nulle - mais array_key_exists() fonctionne correctement dans ce cas.

pour certaines comparaisons, Icon définit explicitement une variable inutilisée comme retournant &null de sorte que vous utilisez le test is-null dans L'icône pour également vérifier une variable désactivée. C'est les choses plus faciles. D'un autre côté, Visual BASIC a plusieurs états pour une variable qui n'a pas de valeur (Null, Empty, Nothing, ...), et vous avez souvent de vérifier plus d'un d'entre eux. Ceci est connu pour être une source de bugs.

0
répondu staticsan 2009-01-06 21:50:57

selon le manuel PHP pour la fonction empty ()," déterminez si une variable est considérée comme vide. Une variable est considérée comme vide si elle N'existe pas ou si sa valeur est égale à FALSE. empty () ne génère pas d'avertissement si la variable n'existe pas."(Mon emphase.) Cela signifie que la fonction empty () devrait être considérée comme la "meilleure façon de tester L'existence D'une variable en PHP", selon la Question de titre.

cependant, ce n'est pas suffisant, parce que le la fonction empty() peut être dupée par une variable qui existe et qui est définie à NULL.

j'interromps ma réponse précédente pour présenter quelque chose de mieux, parce qu'elle est moins lourde que ma réponse originale (qui suit cette interruption, pour comparer).

  function undef($dnc) //do not care what we receive
  { $inf=ob_get_contents();             //get the content of the buffer
    ob_end_clean();                     //stop buffering outputs, and empty the buffer
    if($inf>"")                         //if test associated with the call to this function had an output
    { if(false!==strpos($inf, "Undef"); //if the word "Undefined" was part of the output
        return true;                    //tested variable is undefined
    }
    return false;                       //tested variable is not undefined
  }

deux lignes de code simples peuvent utiliser la fonction ci-dessus pour révéler si une variable n'est pas définie:

  ob_start();                           //pass all output messages (including errors) to a buffer
  if(undef($testvar===null))            //in this case the variable being tested is $testvar

vous pouvez suivre ces deux lignes avec n'importe quoi approprié, comme dans cet exemple:

    echo("variable is undefined");
  else
    echo("variable exists, holding some value");

je voulais placer l'appel à ob_start() et le ($testvar==null) à l'intérieur de la fonction, et simplement passer la variable à la fonction, mais cela ne fonctionne pas. Même si vous essayez d'utiliser "passer par référence" de la variable à la fonction, la variable devient définie, et alors la fonction ne peut jamais détecter qu'elle avait été précédemment non définie. Ce qui est présenté ici est un compromis entre ce que je voulais faire, et ce que en fait, il fonctionne.

ce qui précède implique qu'il existe une autre façon d'éviter de toujours exécuter le message d'erreur" variable non définie". (L'hypothèse ici est, empêcher un tel message est pourquoi vous voulez tester pour voir si une variable est non définie.)

   function inst(&$v) { return; }  //receive any variable passed by reference; instantiates the undefined

il suffit d'appeler cette fonction avant de faire quelque chose à votre $ testvar:

   inst($testvar);                //The function doesn't affect any value of any already-existing variable

la valeur de la variable nouvellement instanciée est définie à null, bien sûr!

(fin de L'Interruption)

donc, après quelques études et des expériences, voici quelque chose garanti pour travailler:

 function myHndlr($en, $es, $ef, $el)
 { global $er;
   $er = (substr($es, 0, 18) == "Undefined variable");
   return;
 }

 $er = false;
 if(empty($testvar))
 { set_error_handler("myHndlr");
   ($testvar === null);
   restore_error_handler();
 }
 if($er)  // will be 1 (true) if the tested variable was not defined.
 { ; //do whatever you think is appropriate to the undefined variable
 }

l'explication: une variable $ er est initialisée à une valeur par défaut de "no error". Une "fonction de gestionnaire" est défini. Si $testvar (la variable que nous voulons savoir si elle n'est pas définie ou non) passe le test préliminaire de la fonction empty (), alors nous faisons le test plus approfondi. Nous appelons l' set_error_handler () fonction pour utiliser la fonction handler définie précédemment. Ensuite, nous faisons une simple comparaison d'identité avec $testvar, qui si elle N'est pas définie déclenche une erreur. La fonction handler capture l'erreur et effectue des tests spécifiques pour voir si la raison de l'erreur est le fait que la variable n'est pas définie. Le résultat est placé dans la variable d'information d'erreur $er, que nous pouvons tester plus tard pour faire ce que nous voulons à la suite de savoir avec certitude si $testvar était définir. Parce que nous n'avons besoin que de la fonction handler pour ce but limité, nous restaurons la fonction de traitement des erreurs d'origine. La fonction" myHndlr " n'a besoin d'être déclarée qu'une seule fois; l'autre code peut être copié à n'importe quel endroit approprié, pour $testvar ou toute autre variable que nous voulons tester de cette façon.

0
répondu vernonner3voltazim 2014-06-19 05:23:31

je pense que la seule solution est de "151920920 rapport" avis avec

error_reporting(E_ALL); // Enables E_NOTICE

mais vous devrez corriger toutes les notices générées par des variables non définies, des constantes, des touches de tableau, des propriétés de classe entre autres. Une fois que vous aurez fait cela, vous n'aurez plus à vous soucier de la différence entre les variables nulles et non déclarées, et l'ambiguïté disparaît.

Activation avis de déclaration pourrait ne pas être une bonne alternative dans toutes les situations, mais il ya de bonnes raisons pour le permettre:

Pourquoi devrais-je corriger des erreurs D'E_NOTICE?

dans mon cas a été plus d'un an de travail dans un proyect sans elle, mais a été utilisé pour être prudent sur la déclaration des variables, il était donc rapide à la transition.

0
répondu mikl 2017-05-23 12:10:11

la seule façon de savoir si une variable est définie dans le champ d'application actuel ( $GLOBALS n'est pas digne de confiance) est array_key_exists( 'var_name', get_defined_vars() ) .

0
répondu Kostas Podias 2017-10-10 00:35:19

, je préfère utiliser pas vide comme la meilleure méthode pour vérifier l'existence d'une variable a) existe, et b) n'est pas nulle.

if (!empty($variable)) do_something();
-1
répondu Hal 2011-03-07 22:28:42