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 相关文章推荐
PHP 和 HTML
Oct 09 PHP
基于mysql的bbs设计(一)
Oct 09 PHP
基于PHP Socket配置以及实例的详细介绍
Jun 13 PHP
php实现MD5加密16位(不要默认的32位)
Aug 12 PHP
php分页示例分享
Apr 30 PHP
JavaScript创建命名空间的5种写法
Jun 24 PHP
ThinkPHP框架安全实现分析
Mar 14 PHP
PHP使用stream_context_create()模拟POST/GET请求的方法
Apr 02 PHP
PHP命名空间namespace用法实例分析
Sep 27 PHP
PHP编程获取各个时间段具体时间的方法
May 26 PHP
php微信开发之谷歌测距
Jun 14 PHP
PHP数据对象映射模式实例分析
Mar 29 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
php面向对象全攻略 (八)重载新的方法
2009/09/30 PHP
php中使用preg_replace函数匹配图片并加上链接的方法
2013/02/06 PHP
PHP常用的文件操作函数经典收藏
2013/04/02 PHP
WIFI万能钥匙密码查询接口实例
2015/09/28 PHP
php制作圆形用户头像的实例_自定义封装类源代码
2017/09/18 PHP
javascript 获取模态窗口的滚动位置代码
2013/08/06 Javascript
js 时间函数应用加、减、比较、格式转换的示例代码
2013/08/23 Javascript
js写的评论分页(还不错)
2013/12/23 Javascript
jquery插件开发之实现google+圈子选择功能
2014/03/10 Javascript
页面get请求 中文参数方法乱码问题的快速解决方法
2016/05/31 Javascript
bootstrap精简教程_动力节点Java学院整理
2017/07/14 Javascript
jQuery实现弹窗下底部页面禁止滑动效果
2017/12/19 jQuery
详解vue填坑之解决部分浏览器不支持pushState方法
2018/07/12 Javascript
vue 父组件给子组件传值子组件给父组件传值的实例代码
2019/04/15 Javascript
[02:09:59]火猫TV国士无双dota2 6.82版本详解(下)
2014/09/29 DOTA
[02:07]TI9显影之尘系列 - Vici Gaming
2019/08/20 DOTA
python创建关联数组(字典)的方法
2015/05/04 Python
python开发之tkinter实现图形随鼠标移动的方法
2015/11/11 Python
python中import学习备忘笔记
2017/01/24 Python
python之DataFrame实现excel合并单元格
2021/02/22 Python
python制作抖音代码舞
2019/04/07 Python
python利用7z批量解压rar的实现
2019/08/07 Python
Python API自动化框架总结
2019/11/12 Python
Python 词典(Dict) 加载与保存示例
2019/12/06 Python
python 解决print数组/矩阵无法完整输出的问题
2020/02/19 Python
Python: tkinter窗口屏幕居中,设置窗口最大,最小尺寸实例
2020/03/04 Python
python 轮询执行某函数的2种方式
2020/05/03 Python
Python下载的11种姿势(小结)
2020/11/18 Python
Canvas实现保存图片到本地的示例代码
2018/06/28 HTML / CSS
为世界各地的女性设计和生产时尚服装:ROMWE
2016/09/17 全球购物
Deichmann英国:德国鞋类零售商
2021/01/30 全球购物
应用电子专业学生的自我评价
2013/10/16 职场文书
房产转让协议书(2014版)
2014/09/30 职场文书
长辈生日祝福语大全(72句)
2019/08/09 职场文书
MySQL 语句执行顺序举例解析
2022/06/05 MySQL
MySQL数据库配置信息查看与修改方法详解
2022/06/25 MySQL