php中的幻术方法

WBOY
發布: 2016-06-13 12:14:36
原創
1033 人瀏覽過

php中的魔术方法

PHP魔术方法:

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为"魔术方法"(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。


__construct(),类的构造函数__destruct(),类的析构函数__call(),在对象中调用一个不可访问方法(私有或者不存在)时调用__callStatic(),用静态方式中调用一个不可访问方法时调用__get(),获得一个类的成员变量时调用__set(),设置一个类的成员变量时调用__isset(),当对不可访问属性调用isset()或empty()时调用__unset(),当对不可访问属性调用unset()时被调用。__sleep(),执行serialize()时,先会调用这个函数__wakeup(),执行unserialize()时,先会调用这个函数__toString(),类被当成字符串时的回应方法__invoke(),调用函数的方式调用一个对象时的回应方法__set_state(),调用var_export()导出类时,此静态方法会被调用。__clone(),当对象复制完成时调用
登入後複製

__construct()和__destruct()
构造函数__construct()在对象被创建的时候调用,析构函数__destruct()在对象消亡的时候被调用

<?php &#160;class ConDes{&#160;&#160;&#160; protected $a = &#39;&#39;;&#160;&#160;&#160; function __construct(){&#160;&#160;&#160;&#160;&#160;&#160;&#160; echo &#39;在构造函数中<br>';    }    function __destruct(){        echo '在析构函数中<br>';    }}$val = new ConDes();unset($val);?><pre name="code" class="php">
登入後複製

登入後複製
输出:

在构造函数中在析构函数中

__call()和__callStatic()在对象中调用一个不可访问方法时会调用这两个方法,后者为静态方法。

<?php &#160;class MethodTest &#160;{&#160;&#160;&#160; public function __call ($name, $arguments) {&#160;&#160; &#160;var_dump($arguments);&#160;&#160;&#160;&#160;&#160;&#160;&#160; echo "object method $name and ".implode(&#39;,&#39;,$arguments)."<br>";    }    public static function __callStatic ($name, $arguments) {        echo "static method $name and ".implode(',',$arguments)."<br>";    }}$obj = new MethodTest;$obj->runTest('in object context','another arg');MethodTest::runTest('in static context');  ?>
登入後複製
输出:

array (size=2)
  0 => string 'in object context' (length=17)
  1 => string 'another arg' (length=11)

object method runTest and in object context,another arg
static method runTest and in static context


__get(),__set(),__isset()和__unset()

当获取一个不可访问的类成员变量或设置一个不可访问的类成员变量时调用这两个函数。

<?phpclass MethodTest  {    private $data = array();    private $a = &#39;&#39;;    public $bbb = &#39;&#39;;    public function __set($name, $value){        $this->data[$name] = $value;		echo '__set';		var_dump($this->data);    }    public function __get($name){		echo '__get';		var_dump($this->data);        if(array_key_exists($name, $this->data))            return $this->data[$name];        return NULL;    }    public function __isset($name){		echo '__isset';        return isset($this->data[$name]);    }    public function __unset($name){		echo '__unset';        unset($this->data[$name]);    }}$in = new MethodTest();$in->a = 'aaaa';$aaa = $in->a;$res = isset($in->c)? 'set':'not set';echo '<br>'.$res.'<br>';unset($in->a);?>
登入後複製
输出:

__set
array (size=1)
  'a' => string 'aaaa' (length=4)
__get
array (size=1)
  'a' => string 'aaaa' (length=4)
__isset
not set
__unset


__sleep()和__wakeup()

当我们在执行serialize()和unserialize()时,会先调用这两个函数。例如我们在序列化一个对象时,这个对象有一个数据库链接,想要在反序列化中恢复链接状态,则可以通过重构这两个函数来实现链接的恢复。

<span class="hljs-preprocessor"></span>

<?phpclass Connection {&#160;&#160;&#160; public $link;&#160;&#160;&#160; private $server, $username, $password, $db;&#160;&#160; &#160;&#160;&#160;&#160; public function __construct($server, $username, $password, $db)&#160;&#160;&#160; {&#160;&#160;&#160;&#160;&#160;&#160;&#160; $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()    {    echo 'sleep<br>';        return array('server', 'username', 'password', 'db');    }        public function __wakeup()    {    echo 'wakeup<br>';        $this->connect();    }}$a = new Connection('localhost','mosi','moshi','test');$sql = 'select id,username from user limit 1';$res = mysql_query($sql,$a->link);$res = mysql_fetch_array($res);var_dump($res);$sres = serialize($a);mysql_close($a->link);//unset($a);$unsres = unserialize($sres);var_dump($unsres);$sql = 'select id,username from user limit 1';$ress = mysql_query($sql,$unsres->link);$ress = mysql_fetch_array($ress);var_dump($ress);?>
登入後複製
输出:

<span class="hljs-preprocessor">array (size=4)<br>  0 => string '1' (length=1)<br>  'id' => string '1' (length=1)<br>  1 => string 'm0sh1' (length=5)<br>  'username' => string 'm0sh1' (length=5)<br>sleep<br>wakeup<br>object(Connection)[2]<br>  public 'link' => resource(6, mysql link)<br>  private 'server' => string 'localhost' (length=9)<br>  private 'username' => string 'moshi' (length=4)<br>  private 'password' => string 'moshi' (length=5)<br>  private 'db' => string 'test' (length=4)<br>array (size=4)<br>  0 => string '1' (length=1)<br>  'id' => string '1' (length=1)<br>  1 => string 'm0sh1' (length=5)<br>  'username' => string 'm0sh1' (length=5)</span>

<span class="hljs-preprocessor"><br></span>

<span class="hljs-preprocessor">__toString()<br><br>对象当成字符串时的回应方法。例如使用echo $obj;</span>

<span class="hljs-preprocessor"></span>

<?php class TestClass  {    public function __toString() {        return &#39;this is a object&#39;;    }}$class = new TestClass();echo $class;  ?>
登入後複製
输出:

<span class="hljs-preprocessor"></span><span class="hljs-preprocessor"></span>this is a object

这个方法只能返回字符串,而且不可以在这个方法中抛出异常,否则会出现致命错误。


__invoke()

调用函数的方式调用一个对象时的回应方法。

<?phpclass Invoke{	public function __invoke(){		echo &#39;in invoke<br>';	}}class noInvoke{}$obj = new Invoke();$obj();var_dump(is_callable($obj));$obj2 = new noInvoke();//$obj2();var_dump(is_callable($obj2));
登入後複製

输出:

in invoke
boolean true
boolean false


__set_state()

调用var_export()导出类时,此静态方法会被调用。

<?php class A  {    public $var1;    public $var2;	public static function __set_state ($arr) {        $obj = new A;        $obj->var1 = 'var11';        $obj->var2 = $arr['var2'];        return $obj;    }}$a = new A;$a->var1 = 5;$a->var2 = 'foo';var_dump($a);  var_export($a);  eval('$ress = '.var_export($a,true).';');var_dump($ress);?>
登入後複製

输出:

object(A)[1]
  public 'var1' => int 5
  public 'var2' => string 'foo' (length=3)
A::__set_state(array( 'var1' => 5, 'var2' => 'foo', ))
object(A)[2]
  public 'var1' => string 'var11' (length=5)
  public 'var2' => string 'foo' (length=3)


__clone()

当对象复制完成时调用。

<?php class Singleton {      private static $_instance = NULL;    // 私有构造方法     private function __construct() {}    public static function getInstance() {        if (is_null(self::$_instance)) {            self::$_instance = new Singleton();        }        return self::$_instance;    }    // 防止克隆实例    public function __clone(){        die(&#39;Clone is not allowed error: &#39; . E_USER_ERROR);    }}$a = Singleton::getInstance();$b = Singleton::getInstance();if( $a === $b ){	echo &#39;equal<br>';}$c = clone $b;?>
登入後複製

输出:

equal
Clone is not allowed error: 256


PHP 魔术常量:简介在这里

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!