Come anticipato nelle lezioni precedenti, PHP fornisce alcuni metodi magici, i quali ricoprono un ruolo molto importante nella programmazione OOP di PHP. A questo punto della guida, abbiamo già analizzato dei metodi magici: __construct
, __destruct()
e __clone()
. In questa lezione analizzeremo anche questi metodi, attivati al verificarsi di determinati eventi e contrassegnati dal doppio underscore __ iniziale("__") .
Attenzione: PHP tratta tutte le funzioni che iniziano con "__" come metodi magici. Si consiglia quindi di non implementare nomi di funzioni con doppio underscore __ iniziale.
Introduzione ai metodi magici in PHP
Di seguito un elenco dei principali metodi magici disponibili con PHP, essi verranno analizzanti dettagliatamente nei prossimi paragrafi:
Medodo | Descrizione |
---|---|
__construct() |
Il costruttore della classe. Chiamato quando si vuole creare un'istanza della classe. |
__destruct() |
Il distruttore della classe. Questo metodo magico viene chiamato per distruggere o deallocare gli oggetti. |
__call() |
Chiamato quando si cerca di effettuare un'invocazione ad un metodo che non esiste o un metodo privato. |
__callStatic() |
Viene richiamato un metodo inaccessibile (nel contesto statico). |
__get() |
Chiamato quando si tenta di leggere una proprietà inaccessibile. |
__set() |
Chiamato quando si tenta di scrivere una proprietà non accessibile. |
__isset() |
Chiamato quando si invocano le funzioni isset() su campi non accessibili. |
__unset() |
Chiamato quando si invoca la funzione unset() su un campo non accessibile. |
__sleep() |
Viene richiamata la funzione serialize() con un'istanza. |
__wakeup() |
Viene richiamata la funzione unserialize() con un'istanza. |
__toString() |
Chiamato quando l'oggetto è trattato come una stringa, ad esempio, quando si utilizza il comando echo . |
__invoke() |
Chiamato quando si tenta di utilizzare un oggetto come funzione. |
__set_state() |
Metodo statico chiamato quando si invoca la funzione var_export() sulla classe. |
__clone() |
Chiamato quando si invoca il comando clone su un oggetto per generarne una copia. |
__construct e __destruct
__construct()
, è il metodo magico che PHP invocata per creare istanze di oggetti di classe. Accetta qualsiasi numero di argomenti. Il metodo __destruct
, viene chiamato automaticamente dal motore PHP prima che l'oggetto sia distrutto. Risulta molto utile, ad esempio, per chiudere gli handle dei files, le connessioni al database o altre operazioni da eseguire prima che l'oggetto venga distrutto.
<?php
class test{
// dichiarazione costruttore
function __construct() {
echo "Costruttore ";
}
// dichiarazione distruttore
function __destruct() {
echo "Distruttore ";
}
}
$obj = new test(); //__construct viene automaticamente chiamato
// distruzione delle istanze
unset($objT); // stampa "Distruttore"
?>
__call e __callStatic
Il metodo __call
viene chiamato ogni volta che si cerca di eseguire un metodo che non esiste. Accetta 2 parametri: il nome della funzione (metodo chiamato) e l'array contenente i parametri passati al metodo. Per i metodi in un contesto statico si consiglia di utilizzare __callStatic()
.
<?php
class MyClass {
public function __call($name, $arguments) {
echo "<br>"."Chiamata metodo '$name' " . implode(', ', $arguments). "\n";
}
public static function __callStatic($name, $arguments) {
echo "<br>"."Chiamata metodo Static '$name' " . implode(', ', $arguments). "\n";
}
}
$obj = new MyClass;
$obj->runTest('Oggetto nel contesto');
MyClass::runTest('Oggetto nel contesto statico');
?>
__set e __get
Il metodo __set
, viene chiamato quando si cerca di modificare una proprietà inesistente , mentre, il metodo __get
, viene chiamato quando si tenta di leggere una proprietà inesistente. Il seguente esempio illustra l'applicazione dei 2 metodi.
<?php
class Test {
private $testArray = array();
public function __set($prop, $valore) {
$this->testArray[$prop] = $valore;
}
public function __get($prop) {
return $this->testArray[$prop];
}
}
$obj = new Test();
if (!isset($obj->nome)) {
$obj->nome = "Giulia";
}
echo $obj->nome; // Giulia
?>
__isset e __unset
Oltre ai metodi __set
e __get
ci sono altri due metodi utili per esaminare l'impostazione di una proprietà inesistente: __isset
e __unset
.
__isset()
controlla se la proprietà è stata impostata o meno. Accetta un argomento, ossia la proprietà che si desidera testare. Si chiama il metodo __isset
anche per la verifica di proprietà vuote, utilizzando la funzione empty()
. __unset()
svolge la funzione opposta a quella del metodo __isset()
, riceve quindi un argomento che è il nome della proprietà che si vuole disinserire o eliminare.
<?php
class Test {
private $testArray = array();
public function __set($prop, $valore) {
$this->testArray[$prop] = $valore;
}
public function __get($prop) {
return $this->testArray[$prop];
}
public function __isset($prop) {
return isset($this->testArray[$prop]);
}
public function __unset($prop) {
unset($this->testArray[$prop]);
}
}
$obj = new Test();
if (!isset($obj->name)) {
$obj->name = "Giulia";
}
echo $obj->name; // Giulia
?>
__sleep e __wakeup
I metodi magici __sleep()
e __wakeup()
sono chiamati durante la serializzazione di oggetti. Questi forniscono un metodo per ripulire e ripristinare un oggetto prima della serializzazione; quindi in caso di serializzazione e deserializzazione di oggetti, PHP controllerà automaticamente, la presenza nella classe dei due metodi.
__sleep()
viene chiamato quando l'oggetto di una classe sta per essere serializzato. Questo metodo non accetta alcun parametro e restituisce un array contenente i nomi delle proprietà da serializzare e si usa generalmente per operazioni di cleanup.
__wakeup ()
svolge la funzione opposta a quella del metodo __sleep()
. Viene Chiamato quando l'oggetto di una classe sta per essere deserializzato, ad esempio, per riaprire le connessioni ai database o alle risorse esterne. Questo metodo non accetta alcun parametro né restituisce nulla. Si analizzi un esempio a riguardo:
<?php
class Person {
private $name;
private $cf;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setCF($cc) {
$this->cf = $cc;
}
public function getCF() {
return $this->cf;
}
public function __sleep() {
return array("name");
}
public function __wakeup() {
if($this->name == "Giulia") {
$this->cf = "CZZGLI12A44E123K";
}
}
}
$c = new Person();
$c->setName("Giulia");
$c->setCF("CZZPGS80C80703T");
$data = serialize($c)."\n";
var_dump(unserialize($data));
?>
__toString
Questa funziona viene utilizzata per restituire la rappresentazione come stringa di un oggetto.
<?php
class Person {
public function __construct($name) {
$this->name = $name;
}
public function __toString() {
return $this->name;
}
}
$person1 = new Person('Giulia');
echo $person1;
?>
Senza l'utilizzo del metodo __toString()
il tentativo di visualizzare un oggetto come stringa restituirebbe un errore fatale.
Catchable fatal error: Object of class Person could not be converted to string in...
__set_state e __invoke
__set_state
viene azionato quando si esporta un oggetto tramite la funzione var_export()
ed accetta un array che avrà le coppie key/value impostate ai nomi/valori delle proprietà esportate. Il secondo, __invoke
, viene richiamato quando si usa un oggetto come una funzione.
<?php
// __set_state
class MyClass{
public $a;
public $b;
public static function __set_state($arr){
$obj = new MyClass;
$obj->a = $arr['a'];
$obj->b = $arr['b'];
return $obj;
}
}
$obj1 = new MyClass();
$obj1->a = 10;
$obj1->b = 20;
eval('$obj2 = ' . var_export($obj1, true) . ';');
// __invoke
class MyClass2 {
public function __invoke($x) {
echo $x;
}
}
$obj1 = new MyClass2();
$obj1(5);
?>
__clone
Come visto nella lezione dedicata alla clonazione degli oggetti, il metodo __clone
fornisce tutte le funzionalità per la clonazione completa e indipendente di un oggetto: crea un nuovo oggetto identico all'originale copiando tutte le variabili membro.
<?php
class Person {
public $nome;
public $cognome;
public $azienda;
// aggiunta all'interno della definizione della classe del metodo __clone().
public function __clone(){
//associazione
$this->azienda = "Warner Bros.";
}
}
class Azienda {
public $nomeAzienda;
}
$aziendaA = new Azienda();
$aziendaA->nomeAzienda="Html.it";
$person1 = new Person();
$person1->nome="Giulia";
$person1->cognome="Q";
$person1->azienda= $aziendaA;
$person3 = clone $person1;
$person3->nome="Giuseppe";
var_dump($person1);
var_dump($person3);
?>
Non appena PHP eseguirà la clonazione del nuovo oggetto, verrà invocato il metodo __clone()
e l'oggetto clonato sarà accessibile.