您的位置:首页 > 编程语言 > PHP开发

PHP魔术方法总结

2014-11-30 23:18 399 查看
PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。

目前php已有的魔术方法有__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone()。

1、__get、__set

这两个方法是为在类和他们的父类中没有声明的属性而设计的

__get( $property ) 当调用一个未定义的属性时访问此方法

__set( $property, $value ) 给一个未定义的属性赋值时调用

这里的没有声明包括当使用对象调用时,访问控制为proteced,private的属性(即没有权限访问的属性)

<?php
class a
{
public $c = 0;
public $arr = array();

public function __set($k, $v)
{
echo $k . "/n";
echo $v . "/n";

$this->arr[$k] = $v;
}

public function __get($k)
{
echo "The value of $k is " . $this->arr[$k];
}
}
$a = new a;
$a->b = 1; // 成员变量b不存在,所以会调用__set
$a->c = 2; // 成员变量c是存在的,所以不调用__set,无任何输出
$d = $a->b; // 成员变量b不存在,所以会调用__get
?>


2、__isset、__unset

__isset( $property ) 当在一个未定义的属性上调用isset()函数时调用此方法

__unset( $property ) 当在一个未定义的属性上调用unset()函数时调用此方法

与__get方法和__set方法相同,这里的没有声明包括当使用对象调用时,访问控制为proteced,private的属性(即没有权限访问的属性)

<?php
class a
{
public $c = 3;
public $arr = array('a' => 1, 'b' => 2);

public function __isset($k)
{
return isset($this->arr[$k]);
}

public function __unset($k)
{
unset($this->arr[$k]);
}
}
$a = new a;

var_dump(isset($a->a)); // 成员变量a不存在,所以调用__isset,返回true
var_dump(isset($a->c)); // 成员变量c是存在的,没有调用__isset,同样返回true
unset($a->b); // 成员变量b不存在,调用__unset
var_dump($a);
?>


3、__call和__callStatic

__call( $method, $arg_array ) 当调用一个未定义的方法是调用此访求

__callStatic( $method, $arg_array ) 当调用一个未定义的静态方法是调用此访求

这里的未定义的方法包括没有权限访问的方法

<?php
class Caller
{
public function __call($method, $args)
{
echo "Method $method called:/n";
print_r($args);
}

static function __callStatic($method, $args)
{
echo "static:".$method;
}
}

$foo = new Caller();
$foo->test(1, 2);

Caller::test(1,2);
?>


4、__autoload

__autoload 函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。

注意: 在 __autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。

<?php
function __autoload($classname){
$classpath="./".$classname.'.php';
if(file_exists($classpath)){
require_once($classpath);
}
else{
echo 'class file'.$classpath.'not found!';
}
}

$newobj = new ClassA();
$newobj = new ClassB();
?>


5、__construct、__destruct

__construct 构造方法,当一个对象创建时调用此方法,使用此方法的好处是:可以使构造方法有一个独一无二的名称,无论它所在的类的名称是什么.这样你在改变类的名称时,就不需要改变构造方法的名称

__destruct 析构方法,PHP将在对象被销毁前(即从内存中清除前)调用这个方法

默认情况下,PHP仅仅释放对象属性所占用的内存并销毁对象相关的资源.析构函数允许你在使用一个对象之后执行任意代码来清除内存.当PHP决定你的脚本不再与对象相关时,析构函数将被调用.在一个函数的命名空间内,这会发生在函数return的时候.对于全局变量,这发生于脚本结束的时候.如果你想明确地销毁一个对象,你可以给指向该对象的变量分配任何其它值.通常将变量赋值勤为NULL或者调用unset.

<?php
class Test {
function __construct()
{
echo "before";
}
function __destruct()
{
echo "end";
}
}
$t = new Test();
unset($t);
?>
6、__clone

PHP5中的对象赋值是使用的引用赋值,如果想复制一个对象则需要使用clone方法,在调用此方法是对象会自动调用__clone魔术方法。如果在对象复制需要执行某些初始化操作,可以在__clone方法实现

<?php
class  a
{
public   function  __clone()
{
echo   "object cloned/n" ;
}
}
$a  =  new  a;

$b  =  $a ;  // $b只是$a的引用, 不是克隆,所以不调用__clone,没任何输出。
$c  = clone  $a ;  // 调用了__clone,将输出 object cloned
?>


7、__toString

__toString方法在将一个对象转化成字符串时自动调用,比如使用echo打印对象时,如果类没有实现此方法,则无法通过echo打印对象,否则会显示:Catchable fatal error: Object of class test could not be converted to string in 此方法必须返回一个字符串。在PHP 5.2.0之前,__toString方法只有结合使用echo() 或 print()时 才能生效。PHP 5.2.0之后,则可以在任何字符串环境生效(例如通过printf(),使用%s修饰符),但
不能用于非字符串环境(如使用%d修饰符)。从PHP 5.2.0,如果将一个未定义__toString方法的对象 转换为字符串,会报出一个E_RECOVERABLE_ERROR错误。

<?php
class  Str
{
private   $str ;

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

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

$class  =  new  Str( 'Hello' );
echo   $class ;  // 这里对象被转 为了string,所以调用了__toString
?>


8、__sleep、__wakeup

__sleep 串行化的时候用

__wakeup 反串行化的时候调用

serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样,该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。

使用 __sleep 的目的是关闭对象可能具有的任何数据库连接,提交等待中的数据或进行类似的清除任务。此外,如果有非常大的对象而并不需要完全储存下来时此函数也很有用。

相反地,unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在,此函数可以重建对象可能具有的任何资源。

使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。

<?php
class User
{
 public $name;
 public $id;

 function __construct()
 {
  //give user a unique ID 赋予一个不同的ID
  $this->id = uniqid();
 }

 function __sleep()
 {
  //do not serialize this->id 不串行化id
  return(array("name"));
 }

 function __wakeup()
 {
  //give user a unique ID
  $this->id = uniqid();
 }
}

//create object 建立一个对象
$u = new User;
$u->name = "Leon";

//serialize it 串行化 注意不串行化id属性,id的值被抛弃
$s = serialize($u);

//unserialize it 反串行化 id被重新赋值
$u2 = unserialize($s);

//$u and $u2 have different IDs $u和$u2有不同的ID
print_r($u);
print_r($u2);

?>


9、__set_state

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

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

<?php
class A
{
public $name1;
public $name2;

public static function __set_state($an_array)
{
$obj = new A;
$obj->name1 = $an_array['var1'];
$obj->name2 = 'doo';
return $obj;
}
}

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

eval('$b = ' . var_export($a, true) . ';');
var_dump($b);

?>


10、__invoke

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

PHP5.3.0以上版本有效

<?php
class CallableClass
{
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
?>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: