首先你要知道什么是php的魔术方法,它不是变魔术的,如果你想学习变魔术来错地方了哦!

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

作用:利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)

其实很多博客主已经写过这些方法了、、、但是我还是要说一遍。。谁让你来听了呢,码这么多字也不容易看完再走吧!

1.__construct,__destruct
__constuct构建对象的时被调用;
__destruct明确销毁对象或脚本结束时被调用;

  1. class Foo {
  2.  
  3. private $name;
  4. private $link;
  5.  
  6. public function __construct($name) {
  7. $this->name = $name;
  8. }
  9.  
  10. public function __destruct() {
  11. echo 'Destroying: ', $this->name, PHP_EOL;//PHP_EOL代表php的换行符
  12. }
  13. }

打住,先安利一波重载的定义及使用方法:

定义:PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。(我们是通过魔术方法(magic methods)来实现的)

作用:当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。后面将使用"不可访问属性(inaccessible properties)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。

注意:所有的重载方法都必须被声明为 public

2.__get、__set、__isset、__unset、__call、__callStatic  //为啥放一起呢?

__set当给不可访问或不存在属性赋值时被调用
__get读取不可访问或不存在属性时被调用

__isset对不可访问或不存在的属性调用isset()或empty()时被调用
__unset对不可访问或不存在的属性进行unset时被调用

__call调用不可访问或不存在的方法时被调用
__callStatic调用不可访问或不存在的静态方法时被调用

Example #1 使用 __get()__set()__isset() 和 __unset() 进行属性重载

  1. <?php
  2. class PropertyTest {
  3. /** 被重载的数据保存在此 */
  4. private $data = array();
  5.  
  6. /** 重载不能被用在已经定义的属性 */
  7. public $declared = 1;
  8.  
  9. /** 只有从类外部访问这个属性时,重载才会发生 */
  10. private $hidden = 2;
  11.  
  12. public function __set($name, $value)
  13. {
  14. echo "Setting '$name' to '$value'\n";
  15. $this->data[$name] = $value;
  16. }
  17.  
  18. public function __get($name)
  19. {
  20. echo "Getting '$name'\n";
  21. if (array_key_exists($name, $this->data)) {
  22. return $this->data[$name];
  23. }
  24.  
  25. $trace = debug_backtrace();
  26. trigger_error(
  27. 'Undefined property via __get(): ' . $name .
  28. ' in ' . $trace[0]['file'] .
  29. ' on line ' . $trace[0]['line'],
  30. E_USER_NOTICE);
  31. return null;
  32. }
  33.  
  34. /** PHP 5.1.0之后版本 */
  35. public function __isset($name)
  36. {
  37. echo "Is '$name' set?\n";
  38. return isset($this->data[$name]);
  39. }
  40.  
  41. /** PHP 5.1.0之后版本 */
  42. public function __unset($name)
  43. {
  44. echo "Unsetting '$name'\n";
  45. unset($this->data[$name]);
  46. }
  47.  
  48. /** 非魔术方法 */
  49. public function getHidden()
  50. {
  51. return $this->hidden;
  52. }
  53. }
  54.  
  55. echo "<pre>\n";
  56.  
  57. $obj = new PropertyTest;
  58.  
  59. $obj->a = 1;
  60. echo $obj->a . "\n\n";
  61.  
  62. var_dump(isset($obj->a));
  63. unset($obj->a);
  64. var_dump(isset($obj->a));
  65. echo "\n";
  66.  
  67. echo $obj->declared . "\n\n";
  68.  
  69. echo "Let's experiment with the private property named 'hidden':\n";
  70. echo "Privates are visible inside the class, so __get() not used...\n";
  71. echo $obj->getHidden() . "\n";
  72. echo "Privates not visible outside of class, so __get() is used...\n";
  73. echo $obj->hidden . "\n";
  74. ?>

看完了吗?好好看!

5.__sleep,__wakeup
__sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用

__wakeup当使用unserialize时被调用,可用于做些对象的初始化操作

  1. <?php
  2. class Connection
  3. {
  4. protected $link;
  5. private $server, $username, $password, $db;
  6.  
  7. public function __construct($server, $username, $password, $db)
  8. {
  9. $this->server = $server;
  10. $this->username = $username;
  11. $this->password = $password;
  12. $this->db = $db;
  13. $this->connect();
  14. }
  15.  
  16. private function connect()
  17. {
  18. $this->link = mysql_connect($this->server, $this->username, $this->password);
  19. mysql_select_db($this->db, $this->link);
  20. }
  21.  
  22. public function __sleep()
  23. {
  24. return array('server', 'username', 'password', 'db');
  25. }
  26.  
  27. public function __wakeup()
  28. {
  29. $this->connect();
  30. }
  31. }
  32. ?>

6.__clone
进行对象clone时被调用,用来调整对象的克隆行为

  1. <?php
  2. class SubObject
  3. {
  4. static $instances = 0;
  5. public $instance;
  6.  
  7. public function __construct() {
  8. $this->instance = ++self::$instances;
  9. }
  10.  
  11. public function __clone() {
  12. $this->instance = ++self::$instances;
  13. }
  14. }
  15.  
  16. class MyCloneable
  17. {
  18. public $object1;
  19. public $object2;
  20.  
  21. function __clone()
  22. {
  23.  
  24. // 强制复制一份this->object, 否则仍然指向同一个对象
  25. $this->object1 = clone $this->object1;
  26. }
  27. }
  28.  
  29. $obj = new MyCloneable();
  30.  
  31. $obj->object1 = new SubObject();
  32. $obj->object2 = new SubObject();
  33.  
  34. $obj2 = clone $obj;
  35.  
  36. print("Original Object:\n");
  37. print_r($obj);
  38.  
  39. print("Cloned Object:\n");
  40. print_r($obj2);
  41.  
  42. ?>

7.__toString
当一个类被转换成字符串时被调用

  1. <?php
  2. class SubObject
  3. {
  4. static $instances = 0;
  5. public $instance;
  6.  
  7. public function __construct() {
  8. $this->instance = ++self::$instances;
  9. }
  10.  
  11. public function __clone() {
  12. $this->instance = ++self::$instances;
  13. }
  14. }
  15.  
  16. class MyCloneable
  17. {
  18. public $object1;
  19. public $object2;
  20.  
  21. function __clone()
  22. {
  23.  
  24. // 强制复制一份this->object, 否则仍然指向同一个对象
  25. $this->object1 = clone $this->object1;
  26. }
  27. }
  28.  
  29. $obj = new MyCloneable();
  30.  
  31. $obj->object1 = new SubObject();
  32. $obj->object2 = new SubObject();
  33.  
  34. $obj2 = clone $obj;
  35.  
  36. print("Original Object:\n");
  37. print_r($obj);
  38.  
  39. print("Cloned Object:\n");
  40. print_r($obj2);
  41.  
  42. ?>

8.__set_state
当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。

  1. <?php
  2.  
  3. class A
  4. {
  5. public $var1;
  6. public $var2;
  7.  
  8. public static function __set_state($an_array) // As of PHP 5.1.0
  9. {
  10. $obj = new A;
  11. $obj->var1 = $an_array['var1'];
  12. $obj->var2 = $an_array['var2'];
  13. return $obj;
  14. }
  15. }
  16.  
  17. $a = new A;
  18. $a->var1 = 5;
  19. $a->var2 = 'foo';
  20.  
  21. eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
  22. // 'var1' => 5,
  23. // 'var2' => 'foo',
  24. // ));
  25. var_dump($b);
  26.  
  27. ?>

enmmm,我知道你记不住的。。这么多谁记得住啊,好烦啊、、、别,这还没讲完呢,更多方法请参考PHP的官方文档:http://php.net/manual/zh/,别打我,你自己去看吧,毕竟好东西还是要众乐乐的!了;另外这些代码你最好再编译器中运行一边,不然看完你估计和没看一个样2333 ····

作者原创、转载请注明出处

PHP的重载及魔术方法的更多相关文章

  1. PHP的重载-使用魔术方法实现

    摘录PHP官网对PHP重载的解释: PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法.我们是通过魔术方法(magic method ...

  2. 巧妙的重载魔术方法__call()

    工作半年了,感觉这半年学到的东西比大学四年学到的还要多,主要原因是心静下来了,目标也明确了,不会去整天的和游戏纠缠在一起了.大学时候其实也意识到了玩游戏会影响自己的正常学习和工作的,但是一直控制不了自 ...

  3. php魔术方法——属性重载方法

    php有一类很神奇的方法,这些方法是保留方法,通常不会在外部被显式调用,他们使用双下划线(__)开头,他们被称为魔术方法(Magic Methods).php官方也不建议定义其他双下划线开头的方法. ...

  4. php用魔术方法__call实现类函数重载

    因为php是弱类型语言,不喜欢c++通过改变函数返回相同的值键入的参数的数目和功能将过载!但在需求函数的实际发展可能过载.开发需求,我们能够通过魔术方法__call()来实现函数重载. class T ...

  5. php中的重载以及几个常用的魔术方法示例

    在面向对象语言中,有一个很重要的概念——overload,即重载.所谓重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同.但是,在php中,这个概念跟大多面向对象语言中的“ ...

  6. Pthon魔术方法(Magic Methods)-运算符重载

    Pthon魔术方法(Magic Methods)-运算符重载 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Python运算符对应的魔术方法 1>.比较运算符 <: ...

  7. php魔术方法使用场景

    php魔术方法-----__tostring(),__invoke,__call(),__callStatic ... __tostring(),__invoke() __tostring()方法是在 ...

  8. PHP 类中的魔术方法

    定义: PHP类中以两个下画线“__”开头的方法被称为魔术方法. 分类: 例如:构造方法:__construct:析构方法:__destruct:动态重载:__set().__get().__call ...

  9. php魔术方法罗列

    ##__sleep() 和 __wakeup() 当序列化(serialize)对象时,PHP 将试图在序列动作之前调用该对象的成员函数 __sleep() .__sleep() 方法常用于提交未提交 ...

随机推荐

  1. XML解析【介绍、DOM、SAX详细说明、jaxp、dom4j、XPATH】

    什么是XML解析 前面XML章节已经说了,XML被设计为"什么都不做",XML只用于组织.存储数据,除此之外的数据生成.读取.传送等等的操作都与XML本身无关! XML解析就是读取 ...

  2. java实现excel和数据的交互

    1. 环境要求 本文环境为: 数据库为oracle,jdk为jdk7,依赖jar包为ojdbc6-11.2.0.4.0.jar+poi-3.14.jar 2.POI 使用 1. 建立工作空间 2. 获 ...

  3. appium python andiroid自动化文档整理笔记

    from appium import webdriver import time,unittest,HTMLTestRunner class Testlogin(unittest.TestCase): ...

  4. javascript DOM事件总结

    1 <html> 2 <title>事件</title> 3 <meta charset="utf-8"/> 4 <body& ...

  5. cglib代理

    简介: github地址:https://github.com/cglib/cglib,可以访问这个地址查看cglib源码和相关文档. 简单的摘录了wiki上关于cglib的描述: cglib is ...

  6. 多线程简单实例(1)真的需要synchronized么?

    说道多线程的安全问题,很多人想到就就是加锁.用到synchronized关键字. 那就要先说说synchronized问什么能够保证线程安全了. 首先要了解线程的工作方式:线程工作分为工作内存和主内存 ...

  7. Pycharm中如何加载多个项目?

    今天在使用Pycharm工具练习Python时遇到一个疑问:在已存有项目A工程的前提下如何新建另一个项目B,且两者并存? 基本操作步骤: 在File下拉项中选择"New Project&qu ...

  8. [js高手之路] html5 canvas系列教程 - 线形渐变,径向渐变与阴影设置

    接着上文[js高手之路] html5 canvas系列教程 - 像素操作(反色,黑白,亮度,复古,蒙版,透明)继续. 一.线形渐变 线形渐变指的是一条直线上发生的渐变. 用法: var linear ...

  9. 【转】Keberos认证原理

    前几天在给人解释Windows是如何通过Kerberos进行Authentication的时候,讲了半天也别把那位老兄讲明白,还差点把自己给绕进去.后来想想原因有以下两点:对于一个没有完全不了解Ker ...

  10. Linux脚本入门(1)

    1. Linux 脚本编写基础1.1 语法基本介绍1.1.1 开头程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例 ...