魔术方法

2022-10-19 08:50:48
内容摘要
__construct, __destruct (参看 构造方法和析构方法), __call, __callStatic, __get, __set, __isset, __unset (参看 重载), __sleep, __wakeup, __toString, __set_state 和 __clone 等方法在PHP中被称为“魔术方法”(Magic methods)。 你在命名自己的类方法时不能使用这些方法名。
文章正文

魔术方法

__construct, __destruct (参看 构造方法和析构方法), __call, __callStatic, __get, __set, __isset, __unset (参看 重载), __sleep, __wakeup, __toString, __set_state 和 __clone 等方法在PHP中被称为“魔术方法”(Magic methods)。 你在命名自己的类方法时不能使用这些方法名。
Caution
PHP把所有以__(两个下划线)开头的类方法当成魔术方法。所以你定义自己的类方法时,不要以 __为前缀。

__sleep 和 __wakeup
serialize() 函数会检查是否存在一个魔术方法 __sleep.如果存在,__sleep()方法会先被调用, 然后才执行序列化操作。这个功能可以用于清理对象,并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容,则NULL被序列化,导致 一个E_NOTICE错误。

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

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

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

Example #1 Sleep 和 wakeup
<?php
class Connection {
    protected $link;
    private $server, $username, $password, $db;
    
    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
    
    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }
    
    public function __wakeup()
    {
        $this->connect();
    }
}
?>

__toString

The __toString method allows a class to decide how it will react when it is converted to a string. __toString 方法可以让一个类决定它如何转换成一个字符串。

Example #2 简单示例

<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo) {
        $this->foo = $foo;
    }

    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Hello');
echo $class;
?>

以上例程会输出:
 

Hello
在PHP 5.2.0之前,__toString方法只有结合使用echo() 或 print()时 才能生效。PHP 5.2.0之后,则可以在任何字符串环境生效(例如通过printf(),使用%s修饰符),但 不能用于非字符串环境(如使用%d修饰符)。从PHP 5.2.0,如果将一个未定义__toString方法的对象 转换为字符串,会报出一个E_RECOVERABLE_ERROR错误。

__invoke
当尝试以调用函数的方式调用一个对象时,__invoke 方法会被自动调用。

Note:

本特性只在PHP 5.3.0 及以上版本有效。

Example #3 Using __invoke
<?php
class CallableClass {
    function __invoke($x) {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

以上例程会输出:

int(5)
bool(true)

__set_state

当调用var_export()时,这个静态 方法会被调用(自PHP 5.1.0起有效)。

本方法的唯一参数是一个数组,其中包含按array('property' => value, ...)格式排列的类属性。

Example #4 Using __set_state (PHP 5.1.0及更高版本支持)

<?php

class A
{
    public $var1;
    public $var2;

    public static function __set_state($an_array) // As of PHP 5.1.0
    {
        $obj = new A;
        $obj->var1 = $an_array['var1'];
        $obj->var2 = $an_array['var2'];
        return $obj;
    }
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';

eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
                                            //    'var1' => 5,
                                            //    'var2' => 'foo',
                                            // ));
var_dump($b);

?>

以上例程会输出:

object(A)#2 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
}
代码注释

作者:喵哥笔记

IDC笔记

学的不仅是技术,更是梦想!