172 votes

Référence : Qu'est-ce que la portée des variables, quelles variables sont accessibles à partir d'où et quelles sont les erreurs de type "variable non définie" ?

Note : Il s'agit d'une question de référence pour traiter la portée des variables en PHP. Veuillez fermer toutes les questions correspondant à ce modèle comme étant des doublons de celle-ci.

Qu'est-ce que la "portée des variables" en PHP ? Les variables d'un fichier .php sont-elles accessibles dans un autre ? Pourquoi est-ce que j'obtiens parfois "variable indéfinie" des erreurs ?

192voto

deceze Points 200115

Qu'est-ce que la "portée variable" ?

Les variables ont une "portée" limitée, ou "lieux à partir desquels elles sont accessibles". Ce n'est pas parce que vous avez écrit $foo = 'bar'; une fois quelque part dans votre application ne signifie pas que vous pouvez vous référer à $foo de partout autre à l'intérieur de l'application. La variable $foo a une certaine portée dans laquelle elle est valide et seul le code dans la même portée a accès à la variable.

Comment est défini un scope en PHP ?

C'est très simple : PHP a champ des fonctions . C'est le seul type de séparateur d'étendue qui existe en PHP. Les variables à l'intérieur d'une fonction ne sont disponibles qu'à l'intérieur de cette fonction. Les variables à l'extérieur des fonctions sont disponibles partout à l'extérieur des fonctions, mais pas à l'intérieur des fonctions. Cela signifie qu'il y a une portée spéciale en PHP : la portée mondial portée. Toute variable déclarée en dehors de toute fonction se trouve dans cette portée globale.

Exemple :

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;
}

$foo est dans le mondial l'étendue, $baz est dans un local périmètre intérieur myFunc . Seulement le code à l'intérieur myFunc a accès à $baz . Seulement le code à l'extérieur de myFunc a accès à $foo . Aucun des deux n'a accès à l'autre :

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;

    echo $foo;  // doesn't work
    echo $baz;  // works
}

echo $foo;  // works
echo $baz;  // doesn't work

Portée et dossiers inclus

Limites des fichiers ne pas séparer l'étendue :

a.php

<?php

$foo = 'bar';

b.php

<?php

include 'a.php';

echo $foo;  // works!

Les mêmes règles s'appliquent à include d code comme s'applique à tout autre code : seulement function s separate scope. Pour ce qui est de la portée, vous pouvez considérer l'inclusion de fichiers comme un copier-coller de code :

c.php

<?php

function myFunc() {
    include 'a.php';

    echo $foo;  // works
}

myFunc();

echo $foo;  // doesn't work!

Dans l'exemple ci-dessus, a.php a été inclus dans myFunc , toute variable à l'intérieur de a.php n'ont qu'une portée de fonction locale. Ce n'est pas parce qu'ils apparaître pour être dans la portée globale dans a.php ne signifie pas nécessairement qu'ils le sont, cela dépend en fait du contexte dans lequel ce code est inclus/exécuté.

Qu'en est-il des fonctions à l'intérieur des fonctions et des classes ?

Chaque nouvelle function La déclaration introduit une nouvelle portée, c'est aussi simple que cela.

Fonctions (anonymes) à l'intérieur de fonctions

function foo() {
    $foo = 'bar';

    $bar = function () {
        // no access to $foo
        $baz = 'baz';
    };

    // no access to $baz
}

classes

$foo = 'foo';

class Bar {

    public function baz() {
        // no access to $foo
        $baz = 'baz';
    }

}

// no access to $baz

A quoi sert le scope ?

Traiter les questions de cadrage peut sembler ennuyeux, mais La portée limitée des variables est essentielle pour écrire des applications complexes ! Si chaque variable que vous déclarez devait être disponible partout ailleurs dans votre application, vous vous promèneriez partout sur vos variables sans aucun moyen réel de savoir ce qui change quoi. Il n'y a que peu de noms sensés que vous pouvez donner à vos variables, vous voudrez probablement utiliser la variable " $name "à plusieurs endroits. Si vous ne pouviez avoir ce nom de variable unique qu'une seule fois dans votre application, vous devriez recourir à des schémas de dénomination vraiment compliqués pour vous assurer que vos variables sont uniques et que vous ne modifiez pas la mauvaise variable à partir du mauvais morceau de code.

Observez :

function foo() {
    echo $bar;
}

S'il n'y avait pas d'étendue, que ferait la fonction ci-dessus ? Où se trouve $bar vient-il ? Quel est son état ? Est-il même initialisé ? Devez-vous vérifier à chaque fois ? Ce n'est pas maintenable. Ce qui nous amène à...

Dépasser les limites du champ d'application

La bonne méthode : passer des variables en entrée et en sortie

function foo($bar) {
    echo $bar;
    return 42;
}

La variable $bar entre explicitement dans cette portée en tant qu'argument de fonction. Il suffit de regarder cette fonction pour comprendre d'où proviennent les valeurs avec lesquelles elle travaille. Il est ensuite explicitement renvoie à une valeur. L'appelant a l'assurance de savoir avec quelles variables la fonction va travailler et d'où proviennent ses valeurs de retour :

$baz   = 'baz';
$blarg = foo($baz);

Extension de la portée des variables dans les fonctions anonymes

$foo = 'bar';

$baz = function () use ($foo) {
    echo $foo;
};

$baz();

La fonction anonyme inclut explicitement $foo de sa portée environnante. Notez que ce n'est pas la même chose que mondial l'étendue.

Le mauvais chemin : global

Comme nous l'avons dit précédemment, la portée globale est quelque peu spéciale, et les fonctions peuvent explicitement importer des variables à partir de celle-ci :

$foo = 'bar';

function baz() {
    global $foo;
    echo $foo;
    $foo = 'baz';
}

Cette fonction utilise et modifie la variable globale $foo . Ne faites pas ça ! (À moins que vous ne sachiez vraiment vraiment vraiment ce que vous faites, et même dans ce cas : ne le faites pas !)

Tout ce que voit l'appelant de cette fonction est ceci :

baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!

Il n'y a pas d'indication que cette fonction a une quelconque effets secondaires et pourtant il le fait. Cela devient très facilement un fouillis, car certaines fonctions continuent de modifier et exigeant un état global. Vous voulez que les fonctions soient apatride qui n'agissent que sur leurs entrées et renvoient une sortie définie, quel que soit le nombre de fois où vous les appelez.

Vous devez éviter autant que possible d'utiliser la portée globale de quelque manière que ce soit ; vous ne devez surtout pas "tirer" les variables de la portée globale vers une portée locale.

0 votes

Vous venez de dire de la mauvaise façon pour global alors dites-nous quand nous devons utiliser global ? Et veuillez expliquer (un peu) ce qui est static .. ?

0 votes

@stack Il n'y a pas de "bonne" façon de global . C'est toujours faux. Passer des paramètres de fonction est correct. static est bien expliqué dans le manuel et n'a pas grand-chose à voir avec la portée. En résumé, on peut l'assimiler à une "variable globale de portée". Je m'étends un peu sur son utilisation ici. kunststube.net/statique .

0 votes

Je pense simplement que si une variable php est suffisamment importante pour mériter un statut global, elle mérite une colonne dans une base de données. C'est peut-être un peu exagéré, mais c'est une approche infaillible qui correspond à mon esprit de programmation médiocre.

10voto

alex_edev Points 390

Bien que les variables définies à l'intérieur de la portée d'une fonction ne soient pas accessibles de l'extérieur, cela ne signifie pas que vous ne pouvez pas utiliser leurs valeurs après la fin de la fonction. PHP possède une fonction bien connue static qui est largement utilisé en PHP orienté objet pour définir des méthodes et des propriétés statiques, mais on doit garder à l'esprit que static peuvent également être utilisés à l'intérieur des fonctions pour définir des variables statiques.

Qu'est-ce qu'une "variable statique" ?

La variable statique diffère de la variable ordinaire définie dans la portée de la fonction dans le cas où elle ne perd pas sa valeur lorsque l'exécution du programme quitte cette portée. Considérons l'exemple suivant d'utilisation des variables statiques :

function countSheep($num) {
 static $counter = 0;
 $counter += $num;
 echo "$counter sheep jumped over fence";
}

countSheep(1);
countSheep(2);
countSheep(3);

Résultat :

1 sheep jumped over fence
3 sheep jumped over fence
6 sheep jumped over fence

Si nous avions défini $counter sans static alors la valeur de chaque écho serait la même que celle de $num transmis à la fonction. Utilisation de static permet de construire ce compteur simple sans contournement supplémentaire.

Cas d'utilisation des variables statiques

  1. Pour stocker des valeurs entre les appels consécutifs à la fonction.
  2. Pour stocker des valeurs entre les appels récursifs lorsqu'il n'y a pas moyen (ou pas d'utilité) de les passer en tant que paramètres. objectif) de les passer en tant que paramètres.
  3. Pour mettre en cache une valeur qu'il est normalement préférable de récupérer une fois. Pour exemple, le résultat de la lecture d'un fichier immuable sur le serveur.

Trucs et astuces

Une variable statique n'existe que dans la portée d'une fonction locale. Elle ne peut pas être accessible en dehors de la fonction dans laquelle elle a été définie. Vous pouvez donc être sûr qu'elle gardera sa valeur inchangée jusqu'au prochain appel à cette cette fonction.

Une variable statique ne peut être définie que comme un scalaire ou comme une expression scalaire. (depuis PHP 5.6). Lui attribuer d'autres valeurs conduit inévitablement conduit inévitablement à un échec, du moins au moment où cet article a été écrit. Néanmoins, vous pouvez le faire à la ligne suivante de votre code :

function countSheep($num) {
  static $counter = 0;
  $counter += sqrt($num);//imagine we need to take root of our sheep each time
  echo "$counter sheep jumped over fence";
}

Résultat :

2 sheep jumped over fence
5 sheep jumped over fence
9 sheep jumped over fence

Une fonction statique est en quelque sorte "partagée" entre les méthodes des objets de la même classe. Il est facile de le comprendre en regardant l'exemple suivant :

class SomeClass {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}

$object1 = new SomeClass;
$object2 = new SomeClass;

$object1->foo(); // 1
$object2->foo(); // 2 oops, $object2 uses the same static $x as $object1
$object1->foo(); // 3 now $object1 increments $x
$object2->foo(); // 4 and now his twin brother

Cela ne fonctionne qu'avec des objets de la même classe. Si les objets sont de classes différentes (même s'ils s'étendent l'un l'autre), le comportement des variables statiques sera le même.

La variable statique est-elle le seul moyen de conserver des valeurs entre les appels à une fonction ?

Une autre façon de conserver les valeurs entre les appels de fonction est d'utiliser les fermetures. Les fermetures ont été introduites en PHP 5.3. En deux mots, elles vous permettent de limiter l'accès à un ensemble de variables à l'intérieur d'une fonction à une autre fonction anonyme qui sera le seul moyen d'y accéder. En étant dans une fermeture, les variables peuvent imiter (avec plus ou moins de succès) les concepts de la POO comme les "constantes de classe" (si elles sont passées dans la fermeture par valeur) ou les "propriétés privées" (si elles sont passées par référence) dans la programmation structurée.

Cette dernière permet en fait d'utiliser des fermetures au lieu de variables statiques. C'est toujours au développeur de décider quoi utiliser, mais il faut mentionner que les variables statiques sont définitivement utiles lorsqu'on travaille avec des récursions et méritent d'être remarquées par les développeurs.

2voto

miken32 Points 8438

Je ne posterai pas une réponse complète à la question, car les existants et les Manuel PHP font un excellent travail pour expliquer la plupart de ces choses.

Mais un sujet qui a été manqué est celui de superglobales dont les plus courantes $_POST , $_GET , $_SESSION etc. Ces variables sont des tableaux qui sont toujours disponibles, dans n'importe quelle portée, sans un global déclaration.

Par exemple, cette fonction imprimera le nom de l'utilisateur qui exécute le script de PHP. La variable est disponible pour la fonction sans aucun problème.

<?php
function test() {
    echo $_ENV["user"];
}

La règle générale "les globaux sont mauvais" est typiquement modifiée en PHP en "les globaux sont mauvais mais les superglobaux sont bons", tant que l'on n'en abuse pas. (Toutes ces variables sont inscriptibles, donc elles pourraient être utilisées pour éviter l'injection de dépendances si vous étiez vraiment terrible).

La présence de ces variables n'est pas garantie ; un administrateur peut désactiver tout ou partie d'entre elles à l'aide de la commande variables_order directive sur php.ini mais ce n'est pas un comportement courant.


Une liste des superglobals actuels :

  • $GLOBALS - Toutes les variables globales dans le script actuel.
  • $_SERVER - Informations sur le serveur et l'environnement d'exécution
  • $_GET - Valeurs transmises dans la chaîne de requête de l'URL, quelle que soit la méthode HTTP utilisée pour la demande.
  • $_POST - Valeurs transmises dans une requête HTTP POST avec l'option application/x-www-form-urlencoded ou multipart/form-data Types MIME
  • $_FILES - Fichiers transmis dans une requête HTTP POST avec un nom de fichier de type multipart/form-data Type MIME
  • $_COOKIE - Cookies transmis avec la demande actuelle
  • $_SESSION - Variables de session stockées en interne par PHP
  • $_REQUEST - Généralement, une combinaison de $_GET et $_POST mais parfois $_COOKIES . Le contenu est déterminé par le request_order directive sur php.ini .
  • $_ENV - Les variables d'environnement du script actuel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X