I metodi magici sono metodi speciali predefiniti che vengono chiamati automaticamente quando vengono soddisfatte determinate condizioni, ad esempio quando si cerca di accedere ad una variabile inaccessibile o inesistente o quando un oggetto viene convertito in una stringa.
__construct()
Il metodo __construct() viene eseguito quando si crea un oggetto di una classe.
__destruct()
Il metodo __destruct() viene eseguito quando un oggetto viene cancellato dalla memoria perchè non ha più riferimenti o perchè lo script termina.
__call()
Il metodo __call() viene eseguito quando si tenta di chiamare un metodo che non esiste o non è accessibile.
__callStatic()
Il metodo __call() viene eseguito quando si tenta di chiamare un metodo statico che non esiste o non è accessibile.
__get()
Con il metodo magico __get($nome_variabile) se si cerca di accedere ad una proprietà della classe che non esiste (oppure che è private o protected) anzichè ricevere un errore si riceve il nome della variabile. Se invece la variabile esiste il metodo non viene eseguito. Un caso d'uso è quello di generare dinamicamente un valore per la proprietà non esistente oppure rilanciare un'eccezione.
<?php
class SimpleClass {
function __get($name){
echo "Stai cercando di accedere alla proprietà '" . $name .
"' che non esiste o non è accessibile";
throw new Exception('La proprietà ' . $name . ' non esiste');
}
}
$obj = new SimpleClass();
$obj->value; //non esiste nessuna proprietà value nella classe quindi verrà eseguito il metodo magico
?>
__set()
Con il metodo magico __set($nome_variabile) se si cerca di modificare una proprietà della classe che non esiste (oppure che è private o protected) anzichè ricevere un errore si riceve il nome della variabile. Se invece la variabile esiste il metodo non viene eseguito.
<?php
class SimpleClass {
function __set($name , $value) {
echo "Stai cercando di modificare la proprietà '"
. $name . "' con il valore '" . $value .
"' ma la proprietà non esiste o non è accessibile";
throw new Exception('La proprietà ' . $name . ' non esiste');
}
}
$obj = new SimpleClass();
$obj->value = "Ciao"; // non esiste nessuna proprietà value nella classe
?>
__isset()
Il metodo __isset() viene eseguito quando la funzione isset() viene applicata ad una proprietà non esistente o non accessibile
__unset()
Il metodo __unset() viene eseguito quando la funzione unset() viene applicata ad una proprietà non esistente o non accessibile.
__sleep()
__wakeup()
__serialize()
__unserialize()
__toString()
Il metodo __toString($oggetto) viene eseguito quando si tenta di convertire un oggetto in una stringa, ad esempio per debug.
<?php
class BankAccount
{
private $accountNumber;
public function __toString() {
return "<p>Numero di conto" . $this->accountNumber . "</p>";
}
}
$account = new BankAccount();
//se non ci fosse il metodo __toString() questo darebbe l'errore
//PHP Fatal error: Uncaught Error: Object of class BankAccount could not be converted to string...
echo $account;
echo 'Oggetto conto: ' . $account;
?>
__invoke()
__set_state()
__clone()
Il metodo __clone() viene eseguito al temine del clone di un oggetto.
<?php
class Person
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
$bob = new Person('Bob');
$alex = $bob; //le due variabili puntano allo stesso oggetto nella memoria
$alex->name = 'Alex';
var_dump($bob); //stampa Alex
var_dump($alex);
// con la parola chiave clone si evita il puntamento allo stesso oggetto
$alex = clone $bob;
$alex->name = 'Alex';
var_dump($bob); //stampa Bob
var_dump($alex);
Se l'oggetto ha una proprietà che punta al riferimento di un altro oggetto allora anche il clone punterà allo stesso oggetto:
<?php
class Address
{
public $street;
public $city;
}
class Person
{
public $name;
public $address;
public function __construct($name)
{
$this->name = $name;
$this->address = new Address(); //riferimento all'oggetto della classe Address
}
}
$bob = new Person('Bob');
$bob->address->street = 'via Federico Confalonieri 4';
$bob->address->city = 'Milano';
$alex = clone $bob; //usiamo clone e non =
$alex->name = 'Alex'; //questo non modifica $bob
$alex->address->street = 'corso Protopisani 70'; //questo modifica anche $bob
$alex->address->city = 'San Giovanni a Teduccio'; //questo modifica anche $bob
?>
Per evitare questo nella classe si può usare il metodo __clone() per clonare gli oggetti referenziati dalle proprietà della classe
<?php
class Person
{
public $name;
public $address;
public function __construct($name)
{
$this->name = $name;
$this->address = new Address();
}
public function __clone()
{
$this->address = clone $this->address;
}
}
?>
@TODO fare approfondimento su copia oggetti con serialize e unserialize
__debugInfo()
Il metodo __debugInfo($oggetto) viene eseguito quando si fa il var_dump() di un oggetto.