PHP魔術方法:
__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep( __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   class ConDes {     protected $a = '';     function __construct(){         echo '在构造函数中<br>'; } function __destruct(){ echo '在析构函数中<br>'; } } $val = new ConDes(); unset($val); ?><pre name="code" class="php">
在建構函式中在析構函式中
__call()和__callStatic()在物件中呼叫一個不可存取方法時會呼叫這兩個方法,後者為靜態方法。
<?php class MethodTest { public function __call ($name, $arguments) { var_dump($arguments); echo "object method $name and ".implode(',',$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 runTrunT 和 in object context, runTest and in static context
當取得一個不可存取的類別成員變數或設定一個不可存取的類別成員變數時呼叫這兩個函數。
<?php class MethodTest { private $data = array(); private $a = ''; public $bbb = ''; 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); ?>
array (size=1)
'a' => string 'aaaa' (length=4)
__get
array (size=1)
'a' => string '' (length=4)__isset
not set
__unset
__sleep()和__wakeup()
<span></span><div class="code" style="position:relative; padding:0px; margin:0px;"><pre name="code"><?php
class 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);
?></pre><div class="contentsignin">登入後複製</div></div>輸出:
array (size=4) 0 => string '1' (length=1)<span> 'id' => string '1' (length=1)<br> 1 => string 'm0sh1' (length=1)<br> 1 => string 'm0sh1' <br> 'username' => string 'm0sh1' (length=5)<br>sleep<br>wakeup<br>object(Connection)[2]<br> public 'link' => resource(6, mysql link)<br> private 'link' => resource(6, mysql link)<br> private 'link' => resource(6, mysql link)<br> private 'link' => resource(6, mysql link)<br> private 'link' => resource(6, mysql link)<br> private 'link' => resource(6, mysql link)<br> private 'link' => resource(6, mysql link)<br> localhost' (length=9)<br> private 'username' => string 'moshi' (length=4)<br> private 'password' => string 'moshi' (length=5)<br> private 'db' => string 'test. (length=4)</span>array (size=4)
0 => string '1' (length=1)
1 => string 'm0sh1' (length 1 => string 'm0sh1' (length =5) 'username' => string 'm0sh1' (length=5)
<span><br></span>
__toString()<span></span>
物件當成字串時的回應方法。例如使用echo $obj;<span></span>
<span></span>
<?php class TestClass { public function __toString() { return 'this is a object'; } } $class = new TestClass(); echo $class; ?>
this is a object
__invoke()
<?php class Invoke{ public function __invoke(){ echo '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); ?>
輸出:
public 'var2' => string 'foo' (length=3)
public 'var2' => string 'foo' (length=3)
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('Clone is not allowed error: ' . E_USER_ERROR); } } $a = Singleton::getInstance(); $b = Singleton::getInstance(); if( $a === $b ){ echo 'equal<br>'; } $c = clone $b; ?>