php教程之魔术方法的使用示例(php魔术函数)


Posted in PHP onFebruary 12, 2014
/** PHP把所有以__(两个下划线)开头的类方法当成魔术方法。所以你定义自己的类方法时,不要以 __为前缀。 * */
// __toString、__set、__get__isset()、__unset()
/*
  The __toString method allows a class to decide how it will react when it is converted to a string.
  __set() is run when writing data to inaccessible members.
  __get() is utilized for reading data from inaccessible members.
  __isset() is triggered by calling isset() or empty() on inaccessible members.
  __unset() is invoked when unset() is used on inaccessible members.
 */
class TestClass {
    private $data = array();
    public $foo;
    public function __construct($foo) {
        $this->foo = $foo;
    }
    public function __toString() {
        return $this->foo;
    }
    public function __set($name, $value) {
        echo "__set, Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }
    public function __get($name) {
        echo "__get, Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
    }
    /** As of PHP 5.1.0 */
    public function __isset($name) {
        echo "__isset, Is '$name' set?\n";
        return isset($this->data[$name]);
    }
    /** As of PHP 5.1.0 */
    public function __unset($name) {
        echo "__unset, Unsetting '$name'\n";
        unset($this->data[$name]);
    }
}
$obj = new TestClass('Hello');
echo "__toString, $obj\n";
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n\n"; 
/**
  输出结果如下:
  __toString, Hello
  __set, Setting 'a' to '1'
  __get, Getting 'a'
  __isset, Is 'a' set?
  bool(true)
  __unset, Unsetting 'a'
  __isset, Is 'a' set?
  bool(false)
 **/
 
// __call  __callStatic
/*
  mixed __call ( string $name , array $arguments )
  mixed __callStatic ( string $name , array $arguments )
  __call() is triggered when invoking inaccessible methods in an object context.
  __callStatic() is triggered when invoking inaccessible methods in a static context.
  The $name argument is the name of the method being called.
  The $arguments argument is an enumerated array containing the parameters passed to the $name'ed method.
 */
class MethodTest {
    public function __call($name, $arguments) {
        // Note: value of $name is case sensitive.
        echo "__call, Calling object method '$name' " . implode(', ', $arguments) . "\n";
    }
    /** As of PHP 5.3.0 */
    public static function __callStatic($name, $arguments) {
        // Note: value of $name is case sensitive.
        echo "__callStatic, Calling static method '$name' " . implode(', ', $arguments) . "\n";
    }
}
$obj = new MethodTest;
$obj->runTest('in object context', 'param2', 'param3');
//MethodTest::runTest('in static context'); // As of PHP 5.3.0
echo "\n\n"; 
/**
 输出结果如下:
 __call, Calling object method 'runTest' in object context, param2, param3
  string(10) "__invoke: "
 */
 
// __invoke
/* 
  The __invoke method is called when a script tries to call an object as a function.
  Note: This feature is available since PHP 5.3.0.
*/
class CallableClass {
    function __invoke($x) {
        var_dump($x);
    }
}
$obj = new CallableClass;
//$obj(5);
var_dump('__invoke: ' . is_callable($obj));
echo "\n\n"; 
 
 
// __sleep  __wakeup
/*
  串行化serialize可以把变量包括对象,转化成连续bytes数据. 你可以将串行化后的变量存在一个文件里或在网络上传输. 
  然后再反串行化还原为原来的数据. 你在反串行化类的对象之前定义的类,PHP可以成功地存储其对象的属性和方法. 
  有时你可能需要一个对象在反串行化后立即执行. 为了这样的目的,PHP会自动寻找__sleep和__wakeup方法.
  当一个对象被串行化,PHP会调用__sleep方法(如果存在的话). 在反串行化一个对象后,PHP 会调用__wakeup方法. 
  这两个方法都不接受参数. __sleep方法必须返回一个数组,包含需要串行化的属性. PHP会抛弃其它属性的值. 
  如果没有__sleep方法,PHP将保存所有属性.下面的例子显示了如何用__sleep和__wakeup方法来串行化一个对象. 
  Id属性是一个不打算保留在对象中的临时属性. __sleep方法保证在串行化的对象中不包含id属性. 
  当反串行化一个User对象,__wakeup方法建立id属性的新值. 这个例子被设计成自我保持. 
  在实际开发中,你可能发现包含资源(如图像或数据流)的对象需要这些方法
 */
class User {
    public $name;
    public $id;
    function __construct() {
        //give user a unique ID 赋予一个差别 的ID
        $this->id = uniqid();
    }
    //__sleep返回值的类型是数组,数组中的值是不需要串型化的字段id
    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);
echo "__sleep, __wakeup, s: $s"; //unserialize it 反串行化 id被重新赋值
$u2 = unserialize($s); //$u and $u2 have different IDs $u和$u2有差别 的ID
print_r($u);
print_r($u2);
echo "\n\n"; 
/**
 输出结果如下:
  __sleep, __wakeup, s: O:4:"User":1:{s:4:"name";s:4:"Leon";}
  User Object
  (
  [name] => Leon
  [id] => 4db1b17640da1
  )
  User Object
  (
  [name] => Leon
  [id] => 4db1b17640dbc
  )
 */

// __set_state
/*
  This static method is called for classes exported by var_export() since PHP 5.1.0.
  The only parameter of this method is an array containing exported properties in the form array('property' => value, ...).
 */
class A {
    public $var1;
    public $var2;
    public static function __set_state($an_array) { // As of PHP 5.1.0
        //$an_array打印出来是数组,而不是调用时传递的对象
        print_r($an_array);
        $obj = new A;
        $obj->var1 = $an_array['var1'];
        $obj->var2 = $an_array['var2'];
        return $obj;
    }
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
echo "__set_state:\n";
eval('$b = ' . var_export($a, true) . ';'); 
// $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
echo "\n\n"; 
/**
  输出结果如下:
  __set_state:
  Array
  (
  [var1] => 5
  [var2] => foo
  )
  object(A)#5 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
  }
 */
 
// __clone
class SubObject {
    static $instances = 0;
    public $instance;
    public function __construct() {
        $this->instance = ++self::$instances;
    }
    public function __clone() {
        $this->instance = ++self::$instances;
    }
}
class MyCloneable {
    public $object1;
    public $object2;
    function __clone() {
        // Force a copy of this->object, otherwise
        // it will point to same object.
        $this->object1 = clone $this->object1;
    }
}
$obj = new MyCloneable();
$obj->object1 = new SubObject();
$obj->object2 = new SubObject();
$obj2 = clone $obj;
print("__clone, Original Object:\n");
print_r($obj);
print("__clone, Cloned Object:\n");
print_r($obj2);
echo "\n\n";
/**
 输出结果如下:
 __clone, Original Object:
  MyCloneable Object
  (
  [object1] => SubObject Object
  (
  [instance] => 1
  ) [object2] => SubObject Object
  (
  [instance] => 2
  ))
  __clone, Cloned Object:
  MyCloneable Object
  (
  [object1] => SubObject Object
  (
  [instance] => 3
  ) [object2] => SubObject Object
  (
  [instance] => 2
  )) 
 */
PHP 相关文章推荐
Discuz!5的PHP代码高亮显示插件(黑暗中的舞者更新)
Jan 29 PHP
php生成随机密码的几种方法
Jan 17 PHP
领悟php接口中interface存在的意义
Jun 27 PHP
php生成缩略图示例代码分享(使用gd库实现)
Jan 20 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
Aug 21 PHP
PHP中的魔术方法总结和使用实例
May 11 PHP
php中使用gd库实现下载网页中所有图片
May 12 PHP
php实现微信公众号无限群发
Oct 11 PHP
CI框架扩展系统核心类的方法分析
May 23 PHP
php+flash+jQuery多图片上传源码分享
Jul 27 PHP
PHP基于方差和标准差计算学生成绩的稳定性示例
Jul 04 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
Dec 21 PHP
php-fpm配置详解
Feb 12 #PHP
PHP添加Xdebug扩展的方法
Feb 12 #PHP
php和jquery实现地图区域数据统计展示数据示例
Feb 12 #PHP
php中的路径问题与set_include_path使用介绍
Feb 11 #PHP
php 不使用js实现页面跳转
Feb 11 #PHP
简单的php中文转拼音的实现代码
Feb 11 #PHP
PHP字符串的递增和递减示例介绍
Feb 11 #PHP
You might like
PHP脚本的10个技巧(2)
2006/10/09 PHP
一个简单计数器的源代码
2006/10/09 PHP
php命令行用法入门实例教程
2014/10/27 PHP
简单了解PHP编程中数组的指针的使用
2015/11/30 PHP
php实现图片上传时添加文字和图片水印技巧
2020/04/18 PHP
PHP基于curl模拟post提交json数据示例
2018/06/22 PHP
PHP实现SMTP邮件的发送实例
2018/09/27 PHP
js多级树形弹出一个小窗口层(非常好用)实例代码
2013/03/19 Javascript
ie8 不支持new Date(2012-11-10)问题的解决方法
2013/07/31 Javascript
jquery.cookie() 方法的使用(读取、写入、删除)
2013/12/05 Javascript
jQuery中(function($){})(jQuery)详解
2015/07/15 Javascript
微信小程序 wxapp内容组件 icon详细介绍
2016/10/31 Javascript
Bootstrap CSS布局之图像
2016/12/17 Javascript
js实现图片360度旋转
2017/01/22 Javascript
selenium 与 chrome 进行qq登录并发邮件操作实例详解
2017/04/06 Javascript
jQuery实现简单的滑动导航代码(移动端)
2017/05/22 jQuery
详解vee-validate的使用个人小结
2017/06/07 Javascript
js学习总结之dom2级事件基础知识详解
2017/07/27 Javascript
NodeJs搭建本地服务器之使用手机访问的实例讲解
2018/05/12 NodeJs
微信小程序如何调用新闻接口实现列表循环
2019/07/02 Javascript
关于ckeditor在bootstrap中modal中弹框无法输入的解决方法
2019/09/11 Javascript
原理深度解析Vue的响应式更新比React快
2020/04/04 Javascript
[02:26]DOTA2英雄米拉娜基础教程
2013/11/25 DOTA
Python中类型检查的详细介绍
2017/02/13 Python
浅谈python日志的配置文件路径问题
2018/04/28 Python
python实现归并排序算法
2018/11/22 Python
浅谈Pycharm最有必要改的几个默认设置项
2020/02/14 Python
Python文字截图识别OCR工具实例解析
2020/03/05 Python
Python3使用tesserocr识别字母数字验证码的实现
2021/01/29 Python
html5页面结构_动力节点Java学院整理
2017/07/10 HTML / CSS
印度尼西亚最完整和最大的在线药房网站:Farmaku.com
2019/11/23 全球购物
专业毕业生个性的自我评价
2013/10/03 职场文书
《望庐山瀑布》教学反思
2014/04/22 职场文书
感恩老师演讲稿600字
2014/08/28 职场文书
大三学生学年自我鉴定
2014/09/12 职场文书
2014旅游局党组书记党建工作汇报材料
2014/11/02 职场文书