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.