PHP中将所有__(两个下划线)开头的类方法作为魔术方法,这方法之所以称为魔术方法是因为其实现的功能就如变魔术一样感觉很神奇。在特定的事件下触发,这真的很酷。

__construct()

这个方法应该是最常用的,被称为构造器或者构造方法,当一个对象被实例化时会被首先调用,而在 PHP 框架中一些过滤器,中间件及依赖注入也一般在这个方法中完成。父类的构造器可以被子类继承和重写。

<?php
class A {public function __construct() {echo "This is A construct\n";}
}class B extends A{// 调用父类构造方法,再调用自己的构造方法public function __construct() {parent::__construct();echo "This is B construct\n";}
}class C extends A{// 重写构造方法,之调用自己的构造方法public function __construct() {echo "This is C construct";}
}new A();// This is A construct
new B();// This is A construct This is B construct
new C();// This is c construct
复制代码

以上示例代码将按顺序输出:

This is A construct This is A construct This is B construct This is C construct

构造方法能帮助我们完成一些数据初始化,属性初始化的任务,在实例化类后使得调用类更便利。

__destruct()

析构方法,PHP 将对象销毁前将调用这个方法,这个方法可能对于 PHP 这种运行时间短的脚本可能无意义,但在有些情况下还是具有意义的。

比如你需要一个长时间运行的脚本,设置 set_time_limit(0); 后需要不断执行这个脚本,一般这样的脚本是循环执行一些任务,这其中可能会涉及到频繁的创建某个对象,这时候析构方法就会起到作用,它可以将对象打开的一些资源及时的释放,以防止内存溢出或单个进程占用过多内存。

<?phpclass Log{public function __construct() {$this->created = time();$this->logfile_handle = fopen('/tmp/log.txt', 'w');}public function __destruct() {fclose($this->logfile_handle);}
}
复制代码

__get()与__set()

这两个方法的作用是当调用或设置一个类及其父类方法中未定义的属性时这个方法会被触发。

<?php class MethodTest
{private $data = array();public function __set($name, $value){$this->data[$name] = $value;}public function __get($name){if(array_key_exists($name, $this->data))return $this->data[$name];return NULL;}}class Penguin extends Animal {public function __construct($id) {$this->getPenguinFromDb($id);}public function getPenguinFromDb($id) {// elegant and robust database code goes here}public function __get($field) {if($field == 'name') {return $this->username;}}public function __set($field, $value) {if($field == 'name') {$this->username = $value;}}}
复制代码

在 MethodTest 这个类中使用 get 和 set 将所有不存在的属性都保存在类的 data 属性中,而在Penguin 类中我们连接了数据库或者是数据提供者,由于某些原因数据源中原来的 name 变更为 username ,如果这时要检查所有调用 Penguin 类的地方将 name 换成 username 显然是困难而且无趣的甚至会有忽略的地方,而使用一个 __get 方法我们不用改变外部调用的属性名就可以实现从 name 转变为 username

__call 和 __callStatic

call 和 callStatic 是类似的方法,前者是调用类不存在的方法时执行,而后者是调用类不存在的静态方式方法时执行。正常情况下如果调用一个类不存在的方法 PHP 会抛出致命错误,而使用这两个魔术方法我们可以替换一些更友好的提示或者记录错误调用日志信息、将用户重定向、抛出异常等等,亦或者是如同set 和 get 那样做方法的重命名。

class A
{public static function __callStatic($name, $arguments){   var_dump($name);var_dump($arguments);echo 'unknown static method ' . $name;}function __call($name, $arguments){var_dump($name);var_dump($arguments);echo 'unknown method ' . $name;}
}$a = new A();
$a->agfdgdrsfgdf([123,3213]);
A::sdfsd();
复制代码

__sleep() 和 __wakeup()

当我们执行 serialize()unserialize() 对对象进行操作是时,会调用这两个方法,比如对象有一个数据库链接,想要在反序列化时恢复链接状态,而在序列化时希望将属性键名保存就可以使用这两个魔术方法:

<?php
class Connection
{protected $link;private $server, $username, $password, $db;public function __construct($server, $username, $password, $db){$this->server = $server;$this->username = $username;$this->password = $password;$this->db = $db;$this->connect();}private function connect(){$this->link = mysql_connect($this->server, $this->username, $this->password);mysql_select_db($this->db, $this->link);}public function __sleep(){return array('server', 'username', 'password', 'db');}public function __wakeup(){$this->connect();}
}
复制代码

__clone()

如同名字一样,这个方法在对象被复制是调用,如我们要实现一个单例模式,我们可以用这个魔术方法防止对象被克隆。

<?php
public class Singleton {private static $_instance = NULL;// 私有构造方法 private function __construct() {}public static function getInstance() {if (is_null(self::$_instance)) {self::$_instance = new Singleton();}return self::$_instance;}// 防止克隆实例public function __clone(){die('Clone is not allowed.' . E_USER_ERROR);}
}
复制代码

__toString()

当对象被当做字符串是调用此方法。

PHP 5.2.0 之前,toString() 方法只有在直接使用于 echo 或 print 时才能生效。PHP 5.2.0 之后,则可以在任何字符串环境生效(例如通过 printf(),使用 %s 修饰符),但不能用于非字符串环境(如使用 %d 修饰符)。自 PHP 5.2.0 起,如果将一个未定义 toString() 方法的对象转换为字符串,会产生 E_RECOVERABLE_ERROR 级别的错误。

// Declare a simple class
class TestClass
{public function __toString() {return 'this is a object';}
}class Penguin {public function __construct($name) {$this->species = 'Penguin';$this->name = $name;}public function __toString() {return $this->name . " (" . $this->species . ")\n";}
}$class = new TestClass();
echo $class;$tux = new Penguin('tux');
echo $tux;复制代码

在 TestClass 的调用中我们输出了一个友好的提示,而在 Penguin 我们将对象的属性组合后输出,比如在模板中调用。

__invoke()

当尝试用函数的方式调用一个对象是触发此方法。

PHP 5.3.0 添加

<?php
class CallableClass
{function __invoke($x) {var_dump($x);}
}
$obj = new CallableClass;
$obj(5); // int(5)
var_dump(is_callable($obj)) // bool(true)
复制代码

__set_state()

调用 var_export() 导出类时,此魔术方法被调用。

PHP 5.1.0 添加

<?php
class A
{public $var1;public $var2;public static function __set_state ($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';
var_dump(var_export($a));
复制代码

__debuginfo()#

这个方法在对对象使用 var_dump() 时调用。

PHP 5.6.0 添加

<?php
class C {private $prop;public function __construct($val) {$this->prop = $val;}public function __debugInfo() {return ['propSquared' => $this->prop ** 2,];}
}var_dump(new C(42));
/*
object(C)#1 (1) {["propSquared"]=>int(1764)
}
*/
复制代码

转载于:https://juejin.im/post/5aa7702f518825557f0096bb

PHP 的魔术方法及其应用相关推荐

  1. PHP中魔术方法的用法

    PHP中魔术方法的用法 /** PHP把所有以__(两个下划线)开头的类方法当成魔术方法.所以你定义自己的类方法时,不要以 __为前缀. * */// __toString.__set.__get__ ...

  2. python 类的魔术方法_python中类的魔术方法

    目的:学习python中class的magic methods,提高编程效率. 环境:ubuntu 16.4   python 3.5.2 在学习class时一定会接触到它的magic methods ...

  3. python魔术方法call_php魔术方法__call

    __call是魔术方法中的一个,当程序调用到当前类中未声明或没权限调用的方法时,就会调用__call方法 class test { public function emptyFunc(){ $getA ...

  4. php 魔术方法 说明

    1.__get.__set这两个方法是为在类和他们的父类中没有声明的属性而设计的. ◆__get( $property ) 当调用一个未定义的属性时,此方法会被触发,传递的参数是被访问的属性名. ◆_ ...

  5. php 魔术方法 多继承,day23:单继承多继承菱形继承__init__魔术方法

    原文:https://www.cnblogs.com/libolun/p/13434675.html 单继承 关于继承的一些基本概念 1.什么是子类?什么是父类?如果一个类继承另外一个类,该类叫做子类 ...

  6. Python最会变魔术的魔术方法,我觉得是它

    在上篇文章中,我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系. 但是,文中也提到了一个例外:一个非常神秘的魔术方 ...

  7. php5中魔术方法函数有哪几个,php中的类魔术方法有哪些

    php中的类魔术方法有:1.__sleep,返回一个包含对象中所有应被序列化的变量名称的数组:2.__tostring,返回一个类被当作字符串时要输出的内容:3.__construct,构造方法:4. ...

  8. python 运算符重载_零基础小白Python入门必看:面向对象之典型魔术方法

    魔术方法 查看类的魔术方法 class A: passdir(A) # 可以得到类所有公有成员复制代码 输出结果如下 ['__class__', '__delattr__', '__dict__', ...

  9. php 5.3 construct_PHP 5.3新增魔术方法__invoke概述

    PHP自从5.3版以来就新增了一个叫做__invoke的魔术方法,使用该方法就可以在创建实例后,直接调用对象.如下示例所示: class testClass { public function __i ...

  10. php超全局变量,魔术常量,魔术方法

    整理了下关于php的基础知识,参考了些资料,如下: 超全局变量 超全局变量 - 超全局变量是在全部作用域中始终可用的内置变量: $GLOBALS $GLOBALS - 引用全局作用域中可用的全部变量 ...

最新文章

  1. [C#][Newtonsoft.Json] Newtonsoft.Json 序列化时的一些其它用法
  2. java.lang.UnsatisfiedLinkError解决方法汇集
  3. 李开复开发的国际象棋软件
  4. 数字编码电位器c语言,单片机小白学习之路(三十八)---AD转换电位器编码
  5. Astar2012 总结
  6. ldd /usr/bin/mysql_mysql客户端登录时报mysql: relocation error错误
  7. 查询类网站或成站长淘宝客新金矿
  8. 移动端图片上传后进行压缩功能
  9. easyui页内跳转
  10. java时区_Java时区
  11. 提供SCDN基础版本售卖
  12. 贝叶斯网络节点概率的计算
  13. 2019最新《网易云课堂C++开发工程师案例-网吧收银系统(MFC+ADO)》
  14. 如何删除PPT中自带的切换动画?
  15. 计算机硬盘用u盘维修,硬盘坏道怎么修复-用U盘启动盘工具
  16. 关于GIt的学习,gitee
  17. 苹果手机解压缩软件_360压缩大师360 推出的免费 macOS 解压缩软件
  18. 网络舆情监测是什么工作,网络舆情监测工作方案?
  19. Foxit Reader以及Foxit Phantom如何设置页面固定大小
  20. 职场生存之道,如何与领导相处

热门文章

  1. 数据特征处理pca降维-小结
  2. 心语收集8:若无缘,与之言多,亦废。若有缘,你的存在,就能惊醒他所有的感觉。...
  3. VB APP对象属性一览表 + 灵活使用VB的APP对象
  4. 智能一代云平台(二十四):已安装的Nginx上安装echo插件
  5. 全套安全从业人员必备工具(建议大家收藏这个帖子)
  6. PHP正则表达式的运用
  7. C++ linux 判断文件是否存在
  8. Oracle ERP简介
  9. 亟待学习的内容 提醒贴
  10. python笔记1-准确掌握列表和元组