PHP之魔术方法

_construct(), destruct(), call(), callStatic(), get(), set(), isset(), unset(), sleep(), wakeup(), toString(), invoke(), set_state(), clone() 和 debugInfo() 等方法在 PHP 中被称为”魔术方法”(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用。这里进行详细介绍,感兴趣的小伙伴们可以参考一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__construct(),类的构造函数
__destruct(),类的析构函数
__call(),在对象中调用一个不可访问方法时调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),获得一个类的成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用。
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用。
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息

类的构造函数 __construct()

php中构造方法是对象创建完成后第一个被对象自动调用的方法。在每个类中都有一个构造方法,如果没有显示地声明它,那么类中都会默认存在一个没有参数且内容为空的构造方法。

  • 在同一个类中只能声明一个构造方法,原因是,PHP不支持构造函数重载。
  • 构造方法名称是以两个下画线开始的__construct()

    构造方法的作用

    通常构造方法被用来执行一些有用的初始化任务,如对成员属性在创建对象时赋予初始值。

    代码示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <?php
    class Person
    {
    public $name;
    public $age;
    public $sex;
    /**
    * 显示声明一个构造方法且带参数
    */
    public function __construct($name="",$sex="boy",$age=22)
    {
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
    }

    /**
    * say 方法
    */
    public function say()
    {
    echo "我叫:" . $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age;
    }

    }

创建对象$Person1且不带任何参数

1
2
$Person1 = new Person();
echo $Person1->say(); //输出:我叫:,性别:boy,年龄:22

创建对象$Person2且带参数“小明”

1
2
$Person2 = new Person("小明");
echo $Person2->say(); //输出:我叫:小明,性别:boy,年龄:22

创建对象$Person3且带三个参数

1
2
$Person3 = new Person("李四","男",25);
echo $Person3->say(); //输出:我叫:李四,性别:男,年龄:25

类的析构函数 __destruct()

通过上面的讲解,现在我们已经知道了什么叫构造方法。那么与构造方法对应的就是析构方法。

析构方法允许在销毁一个类之前执行的一些操作或完成一些功能,比如说关闭文件、释放结果集等。

析构方法是PHP5才引进的新内容。

析造方法的声明格式与构造方法 construct() 比较类似,也是以两个下划线开始的方法 destruct() ,这种析构方法名称也是固定的。

析构方法的作用

一般来说,析构方法在PHP中并不是很常用,它属类中可选择的一部分,通常用来完成一些在对象销毁前的清理任务。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
class Person{

public $name;
public $age;
public $sex;

public function __construct($name="", $sex="男", $age=22)
{
$this->name = $name;
$this->sex = $sex;
$this->age = $age;
}

/**
* say 说话方法
*/
public function say()
{
echo "我叫:".$this->name.",性别:".$this->sex.",年龄:".$this->age;
}

/**
* 声明一个析构方法
*/
public function __destruct()
{
echo "我觉得我还可以再抢救一下,我的名字叫".$this->name;
}
}

$Person = new Person("小明");
unset($Person); //销毁上面创建的对象$Person

输出为:

1
我觉得我还可以再抢救一下,我的名字叫小明

类被当成字符串时的回应方法 __toString()

作用

__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。

注意

此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class Person
{
public $sex;
public $name;
public $age;

public function __construct($name="", $age=25, $sex='男')
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}

public function __toString()
{
return 'go go go';
}
}

$person = new Person('小明'); // 初始赋值
echo $person;

输出为:

1
go go go

如果类中没有 __toString() 这个魔术方法运行会发生什么呢?让我们来测试下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class Person
{
public $sex;
public $name;
public $age;

public function __construct($name="", $age=25, $sex='男')
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}

}

$person = new Person('小明'); // 初始赋值
echo $person;

结果为:

1
Recoverable fatal error: Object of class Person could not be converted to string in D:\appserv\www\ch01\1.php on line 18

很明显,页面报了一个致命错误,这是语法所不允许的。

__sleep(),执行serialize()时,先会调用这个函数

serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,则该方法会优先被调用,然后才执行序列化操作。

此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。

如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。

作用

__sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class Person
{
public $sex;
public $name;
public $age;

public function __construct($name="", $age=25, $sex='男')
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}

/**
* @return array
*/
public function __sleep() {
echo "当在类外部使用serialize()时会调用这里的__sleep()方法<br>";
$this->name = base64_encode($this->name);
return array('name', 'age'); // 这里必须返回一个数值,里边的元素表示返回的属性名称
}
}

$person = new Person('小明'); // 初始赋值
echo serialize($person);
echo '<br/>';

结果为:

1
2
当在类外部使用serialize()时会调用这里的__sleep()方法
O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}

__wakeup(),执行unserialize()时,先会调用这个函数

如果说 sleep() 是白的,那么 wakeup() 就是黑的了。

那么为什么呢?

因为:

与之相反,unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。

作用

__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
class Person
{
public $sex;
public $name;
public $age;

public function __construct($name="", $age=25, $sex='男')
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}

/**
* @return array
*/
public function __sleep() {
echo "当在类外部使用serialize()时会调用这里的__sleep()方法<br>";
$this->name = base64_encode($this->name);
return array('name', 'age'); // 这里必须返回一个数值,里边的元素表示返回的属性名称
}

/**
* __wakeup
*/
public function __wakeup() {
echo "当在类外部使用unserialize()时会调用这里的__wakeup()方法<br>";
$this->name = 2;
$this->sex = '男';
// 这里不需要返回数组
}
}

$person = new Person('小明'); // 初始赋值
var_dump(serialize($person));
var_dump(unserialize(serialize($person)));

输出结果为

1
2
3
4
当在类外部使用serialize()时会调用这里的__sleep()方法
string(58) "O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}" 当在类外部使用serialize()时会调用这里的__sleep()方法
当在类外部使用unserialize()时会调用这里的__wakeup()方法
object(Person)#2 (3) { ["sex"]=> string(3) "男" ["name"]=> int(2) ["age"]=> int(25) }

还有很多,这里先讲这几个常用方法,以后补上,这里给出链接

http://www.jb51.net/article/96167.htm

文章目录
  1. 1. 类的构造函数 __construct()
    1. 1.1. 构造方法的作用
    2. 1.2. 代码示例
  2. 2. 类的析构函数 __destruct()
    1. 2.1. 析构方法的作用
    2. 2.2. 代码示例
  3. 3. 类被当成字符串时的回应方法 __toString()
    1. 3.1. 作用
    2. 3.2. 注意
    3. 3.3. 代码示例
  4. 4. __sleep(),执行serialize()时,先会调用这个函数
    1. 4.1. 作用
    2. 4.2. 代码示例
  5. 5. __wakeup(),执行unserialize()时,先会调用这个函数
    1. 5.1. 作用
    2. 5.2. 代码示例
,