- PHP中的魔术方法,指的一般是:以双下划线开头,不需要显示的调用,在特定的条件下,会被自动调用的方法。
- 这里记录了目前为止所有的 魔术方法,一共15个
- 这些魔术方法,几乎都是为了类的实例服务的,这么规定给我们留下了很大的操作空间
- 由于会被自动调用,所以规定的访问权限一般都是 public
- 针对于 属性
- __get():访问不可访问的属性会被自动调用
- __set():设置不可设置的属性会被自动调用
- __isset():试图通过 empty()、isset() 来访问不可访问的属性时会被自动调用
- __unset() :试图在外部通过unset()方法,来删除对象的某一个属性时会被自动调用
- 序列化和反序列化
- __sleep():序列化自动调用
- __wakeup():反序列化自动调用
- 构造和析构
- __construct():创建对象自动调用
- __destruct():销毁对象时自动调用
- 调试输出对象
- __set_state():var_export() 时自动调用
- __debuginfo():var_dump() 时自动调用
- 打印对象
- __toString():将对象当字符串使用时自动调用
- 克隆对象
- __clone():克隆对象时自动调用
- 访问方法
- __call():访问无法访问的非静态方法是自动调用
- __callStatic():访问无法访问的静态方法时调用
- 将对象当成方法时调用
- __invoke():就这个方法不像是其它方法一样成对出现
PHP中所有的魔术方法
1. __construct()
创建对象时调用。构造方法,创建一个类实例自动调用它的构造函数来完成创建,PHP中的构造函数逼向Java不是类名,而是 __construct().
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
}
var_dump(new Person('xs', 'male', 24));
/*
object(Person)#1 (3) {
["name":"Person":private]=>
string(2) "xs"
["gender":"Person":private]=>
string(4) "male"
["age":"Person":private]=>
int(24)
}
*/
2. __destruct()
销毁对象时被自动调用,一般来说,我们并不用去特别设置这个函数。
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __destruct()
{
print '对象被销毁了!';
}
}
$p1 = new Person('xs', 'male', 24);
unset($p1); // 对象被销毁了!
3. __call()
当访问不存在的非静态方法时被自动调用,这个方法接受两个参数,第一个参数是方法的名称,第二参数是一个数组用于保存形参
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __call($name, $arguments)
{
echo '__call is called ' . "\r";
echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);
}
public static function __callStatic($name, $arguments)
{
echo '__callStatic is called ' . "\r";
echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);
}
}
$p1 = new Person('xs', 'male', 24);
$p1->go(1, 2, 3, 4);
/*
__call is called
Method Name :go
Args :1,2,3,4
*/
4. __callStatic()
和__call()类似,当访问不存在静态的方法时会被自动调用
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __call($name, $arguments)
{
echo '__call is called ' . "\r";
echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);
}
public static function __callStatic($name, $arguments)
{
echo '__callStatic is called ' . "\r";
echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);
}
}
$p1 = new Person('xs', 'male', 24);
$p1::go(1, 2, 3, 4);
/*
__callStatic is called
Method Name :go
Args :1,2,3,4
*/
5. __get()
当试图访问获取不到的属性时,会被自动调用,这个方法只有一个参数这个参数是访问的属性名称。
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __get($name)
{
echo '访问的属性无法直接获取' . " $name \r";
}
}
$p1 = new Person('xs', 'male', 24);
// 1. 比如这里我们访问一个私有的属性
$p1->age; // 访问的属性无法直接获取 age
// 2. 访问一个不存在的属性
$p1->go; // 访问的属性无法直接获取 go
6. __set()
当设置私有的属性或者是其他不存在的属性,总之设置当前无法设置的属性时该方法会被自动调用。接收两个参数,第一个参数是被设置的属性,第二个参数是被设置属性的值。
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __set($name, $value)
{
echo "无法设置 $name 为 $value \r";
}
}
$p1 = new Person('xs', 'male', 24);
$p1->age = 10; // 无法设置 age 为 10
$p1->go = 10; // 无法设置 go 为 10
7. __isset()
当试图通过 isset() 或者 empty() 来访问不可访问的属性时调用该方法
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __isset($name)
{
echo "无法通过isset($name) 或者 empty($name) 访问属性$name \r";
}
}
$p1 = new Person('xs', 'male', 24);
isset($p1->age); // 无法通过isset(age) 或者 empty(age) 访问属性age
empty($p1->age); // 无法通过isset(age) 或者 empty(age) 访问属性age
8. __unset()
在对象里面加上了”unset()”这个方法之后,在对象外部使用”unset()”函数删除对象内部的私有成员属性时,自动调用”unset()”函数来帮我们删除对象内部的私有成员属性,这个方法也可以在类的内部定义成私有的。在对象里面加上下面的代码就可以了:
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
private function __unset($name)
{
echo "调用了 unset($name) 删除一个类属性 \r";
unset($this->$name);
}
}
// 删除某个实例的属性
$p1 = new Person('xs', 'male', 24);
unset($p1->age);
var_dump($p1);
/*
调用了 unset(age) 删除一个类属性
object(Person)#1 (2) {
["name":"Person":private]=>
string(2) "xs"
["gender":"Person":private]=>
string(4) "male"
}
*/
9. __sleep()
在类外部使用serialize()时自动调用
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __sleep()
{
echo "当在类外部使用serialize()时会调用这里的__sleep()方法 \r";
$this->name = base64_encode($this->name);
$this->gender = base64_encode($this->gender);
$this->age = base64_encode($this->age);
// 这里必须返回一个数值,里边的元素表示返回的属性名称
return array('name', 'gender', 'age');
}
}
$person = new Person('向上', '男', 24); // 初始赋值
$ser = serialize($person);
echo $ser; // O:6:"Person":3:{s:12:"
10. __wakeup()
反序列化的时候调用
<?php
// ... ....
11. __toString()
直接输出对象引用时自动调用的方法,简单来说就是,对象被当成字符串使用的使用。我们都知道,PHP中是不可以直接 echo $instance,如果我们自己定义并按照个人的需求去类中添加 “__toString()”,就可以了。
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __toString()
{
return
'name :' . $this->name . '\r' .
'gender :' . $this->gender . '\r' .
'age :' . $this->age ;
}
}
echo (new Person('xs', 'male', 24)); // name :xs\rgender :male\rage :24
12. __invoke()
当对象被当成函数去使用的时候会被自动调用
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __invoke()
{
echo '__invoked() is called';
}
}
$p1 = new Person('xs', 'male', 24);
$p1(); // __invoked() is called
13. __set_state()
当调用 var_export() 导出类时,此静态方法会被自动调用. 就是var_export()的回调函数
先不添加这个方法,我们使用 var_export**
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
}
var_export(new Person('向上', '男', 24));
/*
Person::__set_state(array(
'name' => '向上',
'gender' => '男',
'age' => 24,
))
*/
添加这个方法
14. __clone()
克隆对象时被自动调用
<?php
class Person
{
private $name;
private $gender;
private $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __clone()
{
echo 'who clone me';
}
}
$p1 = new Person('xs', 'male', 24);
$p2 = clone $p1; // who clone me
15. __debuglnfo()
该方法在var_dump()类对象的时候被调用,如果没有定义该方法,则var_dump会打印出所有的类属性,5.6以上的版本
<?php
class Person
{
public $name;
public $gender;
public $age;
public function __construct($name, $gender, $age)
{
$this->name = $name;
$this->gender = $gender;
$this->age = $age;
}
public function __debugInfo()
{
return [
'name' => $this->name,
'age' => $this->age,
'gender' => $this->gender
];
}
}
var_dump(new Person('xs', '男', 24));