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 相关文章推荐
PHP+Tidy-完美的XHTML纠错+过滤
Apr 10 PHP
phpMyAdmin 链接表的附加功能尚未激活的问题
Aug 01 PHP
php实现utf-8转unicode函数分享
Jan 06 PHP
php实现遍历目录并删除指定文件中指定内容
Jan 21 PHP
php中删除数组的第一个元素和最后一个元素的函数
Mar 07 PHP
thinkphp3.2实现上传图片的控制器方法
Apr 28 PHP
php、java、android、ios通用的3des方法(推荐)
Sep 09 PHP
thinkphp关于简单的权限判定方法
Apr 03 PHP
利用PHPExcel实现Excel文件的写入和读取
Apr 26 PHP
利用Laravel生成Gravatar头像地址的优雅方法
Dec 30 PHP
PHP实现的最大正向匹配算法示例
Dec 19 PHP
PHP以json或xml格式返回请求数据的方法
May 31 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
松下Panasonic RF-B65电路分析
2021/03/02 无线电
php 字符串中的\n换行符无效、不能换行的解决方法
2014/04/02 PHP
php计算数组相同值出现次数的代码(array_count_values)
2015/01/20 PHP
PHP中加速、缓存扩展的区别和作用详解(eAccelerator、memcached、xcache、APC )
2016/07/09 PHP
PHP巧妙利用位运算实现网站权限管理的方法
2017/03/12 PHP
Laravel框架实现的rbac权限管理操作示例
2019/01/16 PHP
Laravel框架FormRequest中重写错误处理的方法
2019/02/18 PHP
Microsoft Ajax Minifier 压缩javascript的方法
2010/03/05 Javascript
JavaScript使用过程中需要注意的地方和一些基本语法
2010/08/26 Javascript
由JavaScript中call()方法引发的对面向对象继承机制call的思考
2011/09/12 Javascript
javascript解析json数据的3种方式
2014/05/08 Javascript
学习Javascript闭包(Closure)知识
2016/08/07 Javascript
js实现添加可信站点、修改activex安全设置,禁用弹出窗口阻止程序
2016/08/17 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
Json对象和字符串互相转换json数据拼接和JSON使用方式详细介绍(小结)
2016/10/25 Javascript
微信小程序之拖拽排序(代码分享)
2017/01/21 Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
2020/06/19 Javascript
vue中如何实现变量和字符串拼接
2017/06/19 Javascript
javascript+html5+css3自定义提示窗口
2017/06/21 Javascript
使用socket.io制做简易WEB聊天室
2018/01/02 Javascript
如何将你的AngularJS1.x应用迁移至React的方法
2018/02/01 Javascript
微信小程序实现页面跳转传递参数(实体,对象)
2019/08/12 Javascript
js实现漂亮的星空背景
2019/11/01 Javascript
JS实现密码框效果
2020/09/10 Javascript
Python中的赋值、浅拷贝、深拷贝介绍
2015/03/09 Python
Python网络编程 Python套接字编程
2017/09/13 Python
Python探索之静态方法和类方法的区别详解
2017/10/27 Python
Windows下的Python 3.6.1的下载与安装图文详解(适合32位和64位)
2018/02/21 Python
使用python进行拆分大文件的方法
2018/12/10 Python
解决pytorch-yolov3 train 报错的问题
2020/02/18 Python
Python基于xlutils修改表格内容过程解析
2020/07/28 Python
python 中关于pycharm选择运行环境的问题
2020/10/31 Python
美国波西米亚风格服装品牌:Show Me Your Mumu
2018/01/05 全球购物
优衣库美国官网:UNIQLO美国
2018/04/14 全球购物
2014年学生资助工作总结
2014/12/18 职场文书
《从现在开始》教学反思
2016/02/16 职场文书