Modificatori di Accesso PHP OOP: Guida Completa
I modificatori di accesso in PHP OOP (public, protected, private) controllano la visibilità di proprietà, metodi e costanti per un codice sicuro e robusto.
I modificatori di accesso (detti anche parole chiave di visibilità) determinano chi può leggere, modificare o chiamare un membro di una classe. Sono il meccanismo alla base dell'incapsulamento — uno dei concetti fondamentali della Programmazione Orientata agli Oggetti: si espone una superficie pubblica ridotta e sicura, nascondendo i dettagli interni che i chiamanti non dovrebbero toccare.
Questo capitolo tratta le tre parole chiave di visibilità PHP — public, protected e private — cosa consente ciascuna, cosa succede quando si violano le regole, come si comporta la visibilità nell'ereditarietà, e i pattern comuni (getter, setter e promozione del costruttore) che vi si basano. Se le classi sono nuove per te, leggi prima Classi e Oggetti PHP.
I tre modificatori di accesso in sintesi
| Modificatore | All'interno della stessa classe | In una classe figlia | Dall'esterno (es. $obj->member) |
|---|---|---|---|
public | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ❌ |
private | ✅ | ❌ | ❌ |
Puoi applicare un modificatore a proprietà, metodi e costanti di classe. Se ometti il modificatore su un metodo, PHP lo imposta di default a public; su una proprietà devi indicarlo esplicitamente (la vecchia parola chiave var è un alias di public).
Modificatore di accesso public
public è il livello più permissivo. Un membro pubblico può essere acceduto da qualsiasi luogo — all'interno della classe, dalle classi figlie e da qualsiasi codice che detiene l'oggetto. Usalo per l'interfaccia intesa della tua classe: i metodi che i chiamanti sono destinati a usare.
<?php
class User {
public $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$user = new User();
$user->setName("Ada"); // calling a public method
echo $user->getName(); // Ada
echo "\n";
$user->name = "Grace"; // touching a public property directly
echo $user->name; // GraceL'output è:
Ada
GracePoiché $name è public, i chiamanti possono modificarlo direttamente con $user->name = ..., aggirando setName(). Questo è esattamente il motivo per cui le proprietà public sono spesso sconsigliate: si perde la possibilità di validare il valore. Contrassegnare la proprietà come protected o private ed esporla tramite metodi ripristina quel controllo.
Modificatore di accesso protected
protected si colloca nel mezzo. Il membro è raggiungibile dall'interno della classe e da qualsiasi sottoclasse, ma non dal codice esterno. Usalo quando una sottoclasse ha legittimamente bisogno dei dati, ma i chiamanti esterni non dovrebbero averli.
<?php
class User {
protected $email;
protected function setEmail($email) {
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
}
$user = new User();
echo $user->getEmail(); // works: getEmail() is public
$user->setEmail("[email protected]"); // Fatal error: Call to protected method User::setEmail()L'esecuzione di questo codice non stampa nulla per la prima riga (l'email è ancora null) e poi si interrompe con:
PHP Fatal error: Uncaught Error: Call to protected method User::setEmail() from global scopeL'errore è il punto centrale: i membri protected proteggono la classe dall'uso improprio da parte del codice esterno, cooperando comunque con la catena di ereditarietà mostrata di seguito.
Modificatore di accesso private
private è il livello più restrittivo. Il membro è visibile solo all'interno della classe che lo dichiara — nemmeno le sottoclassi possono vederlo. Usa private quando un dettaglio è puramente interno e potrebbe cambiare in qualsiasi momento, come un hash di password o un calcolo in cache.
<?php
class User {
private $password;
public function setPassword($password) {
// hide the real value behind validation
$this->password = password_hash($password, PASSWORD_DEFAULT);
}
public function check($attempt) {
return password_verify($attempt, $this->password);
}
}
$user = new User();
$user->setPassword("s3cret");
var_dump($user->check("s3cret")); // bool(true)
var_dump($user->check("wrong")); // bool(false)L'output è:
bool(true)
bool(false)Tentare di leggere $user->password dall'esterno della classe genera Error: Cannot access private property User::$password. Il chiamante può interagire solo tramite i metodi public setPassword() e check() — l'hash grezzo è sigillato.
Modificatori di accesso ed ereditarietà
Quando una classe figlia estende una classe genitore, eredita i membri del genitore insieme alla loro visibilità. I membri public e protected sono utilizzabili all'interno della classe figlia; quelli private non sono visibili alla classe figlia.
<?php
class User {
protected $email;
protected function setEmail($email) {
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
}
class Admin extends User {
// Admin can call the protected setEmail() because it is a subclass
public function updateEmail($email) {
$this->setEmail($email);
}
}
$admin = new Admin();
$admin->updateEmail("[email protected]");
echo $admin->getEmail(); // [email protected]L'output è:
Una classe figlia può anche ampliare la visibilità (protected → public) quando sovrascrive un membro, ma non può restringerla — sovrascrivere un metodo public come private genera un errore fatale. Per ulteriori informazioni sulla costruzione di gerarchie di classi, vedi Ereditarietà PHP.
Visibilità su costanti e promozione del costruttore
Le costanti di classe accettano gli stessi modificatori (da PHP 7.1). Questo consente di esporre alcune costanti nascondendo i valori di configurazione interni:
<?php
class Order {
public const STATUS_PAID = "paid";
private const TAX_RATE = 0.2; // internal detail
public function total(float $net): float {
return $net * (1 + self::TAX_RATE);
}
}
echo Order::STATUS_PAID; // paid
echo "\n";
echo (new Order())->total(100); // 120L'output è:
paid
120Da PHP 8.0, la promozione delle proprietà del costruttore consente di dichiarare una proprietà e la sua visibilità direttamente nella firma del costruttore, eliminando il codice boilerplate ripetitivo:
<?php
class Point {
public function __construct(
public int $x = 0,
private int $y = 0, // declared, assigned, and made private in one line
) {}
public function describe(): string {
return "x={$this->x}, y={$this->y}";
}
}
echo (new Point(3, 4))->describe(); // x=3, y=4L'output è:
x=3, y=4Vedi Costanti di Classe PHP e Costruttore PHP per il quadro completo di queste funzionalità.
Scegliere il modificatore giusto
- Inizia con il livello più restrittivo (
private) e allentalo solo quando si presenta un'esigenza reale. Questo mantiene piccola la tua API pubblica e facile da modificare in seguito. - Rendi un membro
publicquando fa parte dell'interfaccia da cui dipendono i chiamanti. - Rendilo
protectedquando le sottoclassi — ma non il codice esterno — ne hanno bisogno. - Rendilo
privatequando è un dettaglio implementativo che potrebbe cambiare senza preavviso. - Preferisci le proprietà private/protected con metodi getter/setter pubblici rispetto alle proprietà public, così mantieni il controllo su come i valori vengono letti e scritti. Questa idea fa parte di cosa riguarda la OOP.
Riepilogo
I modificatori di accesso controllano la visibilità dei membri di classe: public consente l'accesso da qualsiasi luogo, protected dalla classe e dalle sue sottoclassi, e private solo dalla classe che li dichiara. Si applicano a proprietà, metodi e costanti, e sono il modo in cui PHP impone l'incapsulamento. Usati correttamente — nascondendo i dettagli dietro una piccola superficie pubblica — rendono il codice più sicuro da modificare e più facile da comprendere.