Qu'est-ce qu'une "portée variable"?
Les variables ont une «portée» limitée, ou des «endroits à partir desquels elles sont accessibles». Ce n'est pas parce que vous avez écrit $foo = 'bar';
une fois quelque part dans votre application que vous pouvez vous référer $foo
de partout ailleurs dans l'application. La variable $foo
a une certaine portée dans laquelle elle est valide et seul le code de la même portée a accès à la variable.
Comment une portée est-elle définie en PHP?
Très simple: PHP a une portée fonctionnelle . C'est le seul type de séparateur de portée qui existe en PHP. Les variables à l'intérieur d'une fonction ne sont disponibles qu'à l'intérieur de cette fonction. Les variables en dehors des fonctions sont disponibles n'importe où en dehors des fonctions, mais pas à l'intérieur d'une fonction. Cela signifie qu'il y a une portée spéciale en PHP: la portée globale . Toute variable déclarée en dehors de toute fonction est dans cette portée globale.
Exemple:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
est dans la portée globale , $baz
est dans une portée locale à l' intérieur myFunc
. Seul le code à l'intérieur myFunc
a accès à $baz
. Seul le code extérieur myFunc
a accès à $foo
. Aucun 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 fichiers inclus
Les limites des fichiers ne séparent pas la portée:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
Les mêmes règles s'appliquent au include
code d que pour tout autre code: seulement function
une portée distincte. Aux fins de la portée, vous pouvez penser à inclure des fichiers tels que copier-coller du code:
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
Dans l'exemple ci-dessus, a a.php
été inclus à l'intérieur myFunc
, toutes les variables à l'intérieur a.php
n'ont qu'une portée de fonction locale. Ce n'est pas parce qu'ils semblent être dans la portée globale de a.php
cela que cela signifie nécessairement qu'ils le sont, cela dépend en fait du contexte dans lequel le code est inclus / exécuté.
Qu'en est-il des fonctions à l'intérieur des fonctions et des classes?
Chaque nouvelle function
déclaration introduit une nouvelle portée, c'est aussi simple que cela.
(anonyme) fonctions à l'intérieur des fonctions
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
Des classes
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
À quoi sert la portée?
Traiter les problèmes de cadrage peut sembler ennuyeux, mais une portée variable limitée est essentielle pour écrire des applications complexes! Si chaque variable que vous déclarez était disponible partout ailleurs dans votre application, vous parcourriez toutes vos variables sans véritable moyen de suivre ce qui change quoi. Il n'y a qu'un nombre limité de noms sensés que vous pouvez donner à vos variables, vous voudrez probablement utiliser la variable " $name
" à plus d'un endroit. Si vous ne pouviez avoir ce nom de variable unique qu'une seule fois dans votre application, vous devrez recourir à des schémas de dénomination très compliqués pour vous assurer que vos variables sont uniques et que vous ne changez pas la mauvaise variable du mauvais morceau de code.
Observer:
function foo() {
echo $bar;
}
S'il n'y avait pas de portée, que ferait la fonction ci-dessus? D'où $bar
vient-il? Quel état a-t-il? Est-il même initialisé? Devez-vous vérifier à chaque fois? Ce n'est pas maintenable. Ce qui nous amène à ...
Traverser les limites de la portée
La bonne façon: faire entrer et sortir des variables
function foo($bar) {
echo $bar;
return 42;
}
La variable $bar
entre explicitement dans cette portée en tant qu'argument de fonction. En regardant simplement cette fonction, il est clair d'où proviennent les valeurs avec lesquelles elle fonctionne. Il renvoie ensuite explicitement une valeur. L'appelant a la confiance nécessaire pour savoir avec quelles variables la fonction fonctionnera et d'où viennent ses valeurs de retour:
$baz = 'baz';
$blarg = foo($baz);
Extension de la portée des variables aux 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 la portée globale .
La mauvaise direction: global
Comme indiqué précédemment, la portée globale est quelque peu spéciale et les fonctions peuvent en importer explicitement des variables:
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
Cette fonction utilise et modifie la variable globale $foo
. Ne faites pas cela! (À moins que vous ne sachiez vraiment vraiment vraiment ce que vous faites, et même alors: 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?!?!!
Rien n'indique que cette fonction ait des effets secondaires , mais c'est le cas. Cela devient très facilement un désordre enchevêtré car certaines fonctions continuent de se modifier et nécessitent un état global. Vous voulez que les fonctions soient sans état , agissant uniquement sur leurs entrées et renvoyant une sortie définie, quel que soit le nombre de fois que vous les appelez.
Vous devez éviter autant que possible d'utiliser la portée globale; vous ne devriez certainement pas "extraire" des variables de la portée globale vers une portée locale.