Che cos'è "ambito variabile"?
Le variabili hanno un "ambito" o "luoghi" limitati da cui sono accessibili ". Solo perché hai scritto $foo = 'bar';
una volta da qualche parte nella tua applicazione non significa che puoi fare riferimento $foo
da qualsiasi altra parte all'interno dell'applicazione. La variabile $foo
ha un determinato ambito entro il quale è valida e solo il codice nello stesso ambito ha accesso alla variabile.
Come viene definito un ambito in PHP?
Molto semplice: PHP ha un ambito di funzione . Questo è l'unico tipo di separatore di ambito esistente in PHP. Le variabili all'interno di una funzione sono disponibili solo all'interno di quella funzione. Le variabili al di fuori delle funzioni sono disponibili ovunque al di fuori delle funzioni, ma non all'interno di alcuna funzione. Ciò significa che esiste un ambito speciale in PHP: l' ambito globale . Qualsiasi variabile dichiarata al di fuori di qualsiasi funzione rientra in questo ambito globale.
Esempio:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
è nell'ambito globale , $baz
è all'interno di un ambito localemyFunc
. Solo il codice interno myFunc
ha accesso a $baz
. Solo il codice esterno myFunc
ha accesso a $foo
. Nessuno dei due ha accesso all'altro:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
echo $foo; // doesn't work
echo $baz; // works
}
echo $foo; // works
echo $baz; // doesn't work
Ambito e file inclusi
I limiti dei file non separano l' ambito:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
Le stesse regole si applicano al include
codice d come per qualsiasi altro codice: solo function
ambito separato. Ai fini dell'ambito, potresti pensare di includere file come copia e incolla codice:
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
Nell'esempio sopra, è a.php
stato incluso all'interno myFunc
, tutte le variabili all'interno a.php
hanno solo un ambito di funzione locale. Solo perché sembrano rientrare nell'ambito globale a.php
non significa necessariamente che lo siano, in realtà dipende dal contesto in cui è incluso / eseguito il codice.
Che dire delle funzioni all'interno di funzioni e classi?
Ogni nuova function
dichiarazione introduce un nuovo ambito, è così semplice.
(anonime) funzioni all'interno delle funzioni
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
classi
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
A cosa serve l'ambito?
Affrontare i problemi di scoping può sembrare fastidioso, ma l' ambito variabile limitato è essenziale per scrivere applicazioni complesse! Se ogni variabile dichiarata fosse disponibile da qualsiasi altra parte della tua applicazione, passeresti da una parte all'altra delle variabili senza un modo reale di tracciare ciò che cambia cosa. Ci sono solo così tanti nomi sensibili che puoi dare alle tue variabili, probabilmente vuoi usare la variabile " $name
" in più di un posto. Se potessi avere questo nome di variabile univoco solo una volta nella tua app, dovresti ricorrere a schemi di denominazione davvero complicati per assicurarti che le tue variabili siano uniche e che non stai cambiando la variabile sbagliata dal pezzo di codice sbagliato.
Osservare:
function foo() {
echo $bar;
}
Se non ci fosse ambito, cosa farebbe la funzione sopra? Da dove $bar
viene Che stato ha? È anche inizializzato? Devi controllare ogni volta? Questo non è mantenibile. Il che ci porta a ...
Attraversare i confini dell'ambito
La strada giusta: passare le variabili dentro e fuori
function foo($bar) {
echo $bar;
return 42;
}
La variabile $bar
entra esplicitamente in questo ambito come argomento della funzione. Solo guardando questa funzione è chiaro da dove provengono i valori con cui lavora. Quindi restituisce esplicitamente un valore. Il chiamante ha la certezza di sapere con quali variabili funzionerà la funzione e da dove provengono i suoi valori di ritorno:
$baz = 'baz';
$blarg = foo($baz);
Estensione dell'ambito delle variabili in funzioni anonime
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
La funzione anonima include esplicitamente $foo
dal suo ambito circostante. Si noti che questo non è lo stesso dell'ambito globale .
La strada sbagliata: global
Come detto prima, l'ambito globale è in qualche modo speciale e le funzioni possono importare esplicitamente variabili da esso:
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
Questa funzione utilizza e modifica la variabile globale $foo
. Non farlo! (A meno che tu non sappia davvero davvero quello che stai facendo, e anche allora: non farlo!)
Tutto il chiamante di questa funzione vede questo:
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
Non ci sono indicazioni che questa funzione abbia effetti collaterali , eppure lo fa. Questo diventa molto facilmente un pasticcio aggrovigliato poiché alcune funzioni continuano a modificarsi e richiedono uno stato globale. Volete che le funzioni siano stateless , agendo solo sui loro input e restituendo output definiti, comunque molte volte le chiamate.
Dovresti evitare di usare l'ambito globale in ogni modo il più possibile; sicuramente non dovresti "estrarre" le variabili dall'ambito globale in un ambito locale.