MENU
Magic Functions
Magic functions are functions that are triggered automatically when special events happen. They can be defined in any class.__construct([$m1,$m2……]) is called when an object is created. A child class can override the parent’s ‘constructor’ with a different arguments signature. $m1, $m2 can be any content type (mixed). __destruct() is called when there are no more references to an object. __clone() is called when an object is cloned.
The destructor is called before the script ends.
__set($s,$m) is called when writing data to undeclared properties. __get($s) is called when reading data from undeclared properties. It can return any type. __isset($s) is triggered by calling isset() or empty() on undeclared properties. It returns a boolean value. __unset($s) is triggered when unset() is used on undeclared properties. <!DOCTYPE html>
<html>
<head></head>
<body><?php
class C{
function __construct($s){ echo "Constructor".$s;}
function __destruct(){ echo "Destructor called. ";}
function __clone(){ echo "__clone() called. ";}
}
$a=new C(" called. "); // Constructor called.
$b=clone $a; // __clone() called.
$a=$b; // Destructor called.
$c=clone $a; // __clone called().
?></body>
</html>Constructor called. __clone() called. Destructor called. __clone() called. Destructor called. Destructor called.
__call($s,$arr) is called when invoking undeclared methods in an object context. It can return any type. __callStatic($s,$arr) is triggered when invoking undeclared methods in a static context. It can return any type. __invoke ([$m1,$m2……]) is called when a script tries to call an object as a function. It can return any type.
__toString() is called when the object is treated like a string. It returns a string.
The destructor is called before the script ends.
Since PHP 5.6, a class may define a __debugInfo() magic method to customize what var_dump() shows for its objects. Normally var_dump() prints every property (including private ones) with its real name and value; if __debugInfo() is defined, var_dump() calls it instead and dumps whatever array it returns:
<!DOCTYPE html>
<html>
<head></head>
<body><?php
class C{
function __set($name,$value){
echo "Trying to set \$$name to $value...<br />";
}
function __get($name){
echo "Trying to get a value from \$$name...<br />";
return 5;
}
function __isset($name){
echo "Checking if \$$name is set...<br />";
return true;
}
function __unset($name){
echo "Trying to unset \$$name...<br />";
}
function __call($name,$arr){
echo "Trying to call $name() with $arr[0]...<br />";
}
static function __callStatic($name,$arr){
echo "Trying to call $name() statically with $arr[0]...<br />";
}
function __invoke($s){
echo "Trying to invoke a function with $s...<br />";
}
function __toString(){
return "Trying to be treated like a string...<br />";
}
}
$a=new C; // $a->x is an undeclared property
$a->x=5;
$b=$a->x;
$c=isset($a->x);
unset($a->x);
$a->x("TEST");
$a::x("TEST");
$a("TEST");
echo $a;
?></body>
</html>Trying to set $x to 5...
Trying to get a value from $x...
Checking if $x is set...
Trying to unset $x...
Trying to call x() with TEST...
Trying to call x() statically with TEST...
Trying to invoke a function with TEST...
Trying to be treated like a string...
Trying to get a value from $x...
Checking if $x is set...
Trying to unset $x...
Trying to call x() with TEST...
Trying to call x() statically with TEST...
Trying to invoke a function with TEST...
Trying to be treated like a string...
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>object(C)#1 (1) {
["propSquared"]=>
int(1764)
}
This is mainly useful in type declarations: a parameter or return type of string|Stringable accepts either a plain string or any object that can be converted to one.
A class doesn't need to declare implements Stringable if it already has a __toString() method.
<!DOCTYPE html>
<html>
<head></head>
<body><?php
class Temperature implements Stringable {
function __construct(private float $celsius) {}
function __toString(): string {
return $this->celsius . " degrees C";
}
}
class Money { // no "implements Stringable" needed
function __construct(private int $cents) {}
function __toString(): string {
return "$" . number_format($this->cents / 100, 2);
}
}
function printLabel(string|Stringable $value): void {
echo "Label: $value<br />";
}
$t = new Temperature(25.5);
$m = new Money(1050);
var_dump($t instanceof Stringable); // true, explicitly declared
var_dump($m instanceof Stringable); // true, added automatically
printLabel($t);
printLabel($m);
printLabel("Plain string");
?></body>
</html>bool(true)
bool(true)
Label: 25.5 degrees C
Label: $10.50
Label: Plain string
Label: $10.50
Label: Plain string