php 魔术函数使用说明


Posted in PHP onFebruary 21, 2010

什么是魔术函数?
对于__开头的函数就命名为魔术函数, 此类函数都在特定的条件下触发的.比如: __set() __get()等
在设置或取不存在的属性时候触发.
有那些魔术函数呢?
总的来说, 有下面几个魔术函数
__construct() __destruct() __get() __set() __isset() __unset() __call() __callStatic()
__sleep() __wakeup() __toString() __set_state() __clone() __autoload()
__construct()当实例化一个对象的时候,这个对象的这个方法首先被调用。
__destruct()当删除一个对象或对象操作终止的时候,调用该方法。

class test1 { 
public function __construct() { 
var_dump(__function__); 
} 
public function __destruct() { 
var_dump(__function__); 
} 
} 
$t1 = new test1 ; 
unset($t1);

__get当试图读取一个并不存在的属性的时候被调用。
__set当试图向一个并不存在的属性写入值的时候被调用。
__isset当试图检测一个并不存在的属性时候被调用。
__unset当试图取消一个并不存在的属性时候被调用。
class test2 { 
public $name3; 
public function __set($key, $value) { 
var_dump(__function__. ' 
KEY:' 
.$key.' 
Value:' 
.$value); 
} 
public function __get($key) { 
var_dump(__function__. 'KEY:'.$key); 
} 
public function __isset($key) { 
var_dump(__function__. ' KEY:'.$key); 
} 
public function __unset($key) { 
var_dump(__function__. ' KEY:'.$key); 
} 
} 
$t =new test2 ; 
$t->name = "steven"; 
$t->name2; 
$t->name3; 
isset($t->name2); 
isset($t->name3); 
unset($t->name4);

__sleep当进行序列化对象时候调用
__wakeup当进行反序列对象时候调用
需要注意一点:
1. __sleep()必须返回一个数组或者对象(一般返回的是$this),返回的值将会被用来做为序列化的
值。
如果不返回这个值,则序列化失败。这也意味着反序列化将不会触发__wakeup事件。
2. 序列化会保存默认赋值的属性.如果要通过实例化赋值的内容,则需要属性在__sleep()返回数组的
指定.
如$id与$id2的区别.
class test3 { 
public $name = "steven"; 
public $id = "1"; public $id2; 
public function __sleep() { 
var_dump(__function__); // 序列化不成功.没有返回值.反序列也失败 // 
return array("name"); // 序列化成功.有返回值.反序列成功.id2属性能被恢复 // 
return array("name", "id2");// 序列化成功.有返回值.反序列成功.id2属性不能被恢复 
return array("name"); } 
public function testEcho() { 
var_dump($this->name); 
var_dump($this->id); 
var_dump($this->id2); 
} 
public function __wakeup() { 
var_dump(__function__); 
$this->testEcho(); 
} 
} 
$t3= new test3 ; 
$t3->id2 = uniqid(); 
$t3s = serialize($t3); 
unserialize($t3s);

__toString当直接打印一个对象的时候,这个方法将会被调用
class test4 { 
public function __toString() { 
return "toString"; 
} 
} 
$t4 = new test4(); 
echo $t4; 
print $t4; 
var_dump($t4); 
print_r($t4);

__call($func, $param) 当尝试调用一个不存在的方法的时候被调用.
这个方法必须有两个参数,第一个为调用的方法名,第二个是一个被调用方法的参数数组。
需要注意的是,当你在一个子类调用父类的private的方法,或者在实例里调用类的非protect方法的
时候,并不会调用__call()
class test5 { 
public function __call($func, $param) { 
var_dump('Function:'.$func); 
var_dump($param); 
} 
} 
$t5 = new test5; 
$t5->echoTest('xx','xx','xx');

__callStatic()当尝试调用一个不存在的静态方法的时候被调用
这个方法必须有两个参数,第一个为调用的方法名,第二个是一个被调用方法的参数数组。
在PHP5.3中出现
class test51 { 
public function __callStatic($fun, $param) { 
var_dump('Function:'.$func); 
var_dump($param); 
} 
} 
test51::test('xx','xx','xx');

__set_state()当用var_export导出实例的时候被调用.此方法有一个参数,为包含所导出的实例的所
有成员属性的一个数组
class test6 { 
public function __set_state($arr){ 
var_dump($arr); 
} 
} 
$t6 = new test6; 
$t6->age = "12"; 
var_export($t6, true); 
var_export($t6); 
eval(' 
$b=' 
.var_export($t6,true).';'); 
print_r($b);

__clone()当克隆实例时候被调用.
注意:
1.在php5里,对象间的赋值总是以地址引用来传递的.
2.如果要以实际值来传递,则需要用到clone关键词
3.clone的只是实例。如果实例中的某个成员属性也是个实例,那么这个成员属性还是会以引用方法被
传递到新的实例。
// 对象间的赋值总是以地址引用来传递的. $t71 $t72的age属性是一样的.
class test71 { 
public $age = 10; 
} 
$t71 = new test71(); 
$t72 = $t71 ; 
var_dump($t71->age) ; 
$t71->age =12 ; 
var_dump($t71->age) ; 
var_dump($t72->age) ; // 如果要以实际值来传递,则需要用到clone关键词 $t73 = clone $t71; $t71->age = 13 ; var_dump($t71->age) ; 
var_dump($t73->age) ; // 如果实例中的某个成员属性也是个实例,那么这个成员属性还是会以引用方法被传递到新的实例。

class test74 { 
public $age = 10; 
public $sub = null; 
} 
class test75 { 
public $age = 11; 
} 
$i = new test74; 
$i->sub = new test75(); 
$i1 =clone $i; 
var_dump($i1->sub->age); 
$i->sub->age = 12; 
var_dump($i1->sub->age);

// $i 和$i1虽然不是指向同一个实例,但是它们的成员属性$sub却是指向同一个实例。这时候,我们必须借
助__clone这个方法来对$sub进行复制。 // $i2和$3指向不同实例.成员属性$sub也指向不同实例.
class test76 { 
public $age = 10; 
public $sub = null; 
public function __clone() { 
$this->sub = clone $this->sub; 
} 
} 
$i2 = new test76(); 
$i2->sub = new test75(); 
$i3 = clone $i2; 
$i2->sub->age = 15 ; 
var_dump($i3->sub->age);

__autoload()函数.当创建一个实例化的时候,如果对应的类不存在,则会被调用
function __autoload($class) { 
 if ( $class == "test8" ){ 
require_once dirname(__FILE__).'/class8.php';  
} 
} 
spl_autoload(); 
$t8 = new test8; 
var_dump($t8->age);
PHP 相关文章推荐
用文本文件制作留言板提示(下)
Oct 09 PHP
别人整理的服务器变量:$_SERVER
Oct 20 PHP
PHP学习笔记之二 php入门知识
Jan 12 PHP
慎用preg_replace危险的/e修饰符(一句话后门常用)
Jun 19 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(四)
Jun 23 PHP
php匹配字符中链接地址的方法
Dec 22 PHP
PHP超全局数组(Superglobals)介绍
Jul 01 PHP
PHP之正则表达式捕获组与非捕获组(详解)
Jul 29 PHP
深入讲解PHP的Yii框架中的属性(Property)
Mar 18 PHP
thinkphp3.2实现上传图片的控制器方法
Apr 28 PHP
PHP智能识别收货地址信息实例
Jan 05 PHP
PHPstorm启用自动换行的方法详解(IDE)
Sep 17 PHP
php microtime获取浮点的时间戳
Feb 21 #PHP
PHP+ajax 无刷新删除数据
Feb 20 #PHP
php 读取文件乱码问题
Feb 20 #PHP
判断是否为指定长度内字符串的php函数
Feb 16 #PHP
支持数组的ADDSLASHES的php函数
Feb 16 #PHP
php htmlspecialchars加强版
Feb 16 #PHP
php 数组二分法查找函数代码
Feb 16 #PHP
You might like
咖啡磨器 如何选购一台适合家用的意式磨豆机
2021/03/05 新手入门
php获取地址栏信息的代码
2008/10/08 PHP
php ss7.5的数据调用 (笔记)
2010/03/08 PHP
php下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
ThinkPHP中ajax使用实例教程
2014/08/22 PHP
PHP连接Nginx服务器并解析Nginx日志的方法
2015/08/16 PHP
PHP与Ajax相结合实现登录验证小Demo
2016/03/16 PHP
PHP实现微信小程序用户授权的工具类示例
2019/03/05 PHP
IE、FF浏览器下修改标签透明度
2014/01/28 Javascript
深入理解JS中的变量及作用域、undefined与null
2014/03/04 Javascript
纯Javascript实现ping功能的方法
2015/03/20 Javascript
javascript实现tab响应式切换特效
2016/01/29 Javascript
javascript实现仿百度图片的瀑布流加载效果
2016/04/20 Javascript
JS出现失效的情况总结
2017/01/20 Javascript
ES7中利用Await减少回调嵌套的方法详解
2017/11/01 Javascript
AngularJS实现的锚点楼层跳转功能示例
2018/01/02 Javascript
vue根据值给予不同class的实例
2018/09/29 Javascript
javascript中floor使用方法总结
2019/02/02 Javascript
nodejs微信开发之接入指南
2019/03/17 NodeJs
Python中设置变量作为默认值时容易遇到的错误
2015/04/03 Python
Python遍历某目录下的所有文件夹与文件路径
2018/03/15 Python
Python发送邮件功能示例【使用QQ邮箱】
2018/12/04 Python
Python利用 utf-8-sig 编码格式解决写入 csv 文件乱码问题
2020/02/21 Python
解决Keras中Embedding层masking与Concatenate层不可调和的问题
2020/06/18 Python
美国隐形眼镜零售商:LensPure
2019/03/10 全球购物
公司离职证明范本
2014/01/13 职场文书
开学季活动策划方案
2014/02/28 职场文书
葛优非诚勿扰搞笑征婚台词
2014/03/17 职场文书
党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
喝酒驾驶检讨书
2014/10/01 职场文书
大学生自我评价范文
2015/03/03 职场文书
葬礼主持词
2015/07/02 职场文书
详解PHP用mb_string处理windows中文字符
2021/05/26 PHP
SpringRetry重试框架的具体使用
2021/07/25 Java/Android
Pyhton爬虫知识之正则表达式详解
2022/04/01 Python
Java虚拟机内存结构及编码实战分享
2022/04/07 Java/Android