PHP中的12个魔术方法
PHP中的12个魔术方法
这个标题有点牵强因为php有不只12种魔术方法, 但是这些将会引导你使用php魔术方法一个好的开始。它可能魔幻,但是并不需要魔杖。
PHP中有一些特殊的函数和方法,这些函数和方法相比普通方法的特殊之处在于: 用户代码通常不会主动调用, 而是在特定的时机会被PHP自动调用(这些方法在php特定事件下将会被触发)。这些'魔术'方法拥有者特殊的名字,在PHP中通常以"__"打头的方法都作为魔术方法, 所以通常不要定义以"__"开头的函数或方法。
这可能听起来有点自动魔法但是它真的很酷的,我们已经看过一个简单的例子在上一篇博客中,即我们使用一个构造器-使用这个作为我们第一个例子.
__construct
构造器是一个魔术方法,当对象被实例化时它会被调用。在一个类声明时它常常是第一件做的事但是没得必要他也像其他任何方法在类中任何地方都可以声明,构造器也能像其他方法样继承。如果我们想到以前继承例子从介绍到oop,我们能添加构造方法到Animal 类中,如:
1
|
class Animal{
|
2
|
|
3
|
public function __construct() {
|
4
|
$this ->created = time();
|
5
|
$this ->logfile_handle = fopen ( '/tmp/log.txt' , 'w' );
|
6
|
}
|
7
|
|
8
|
}
|
现在我们创建一个类来继承Animal类 - Penguin类!不添加任何属性和方法在Penguin类中,我们能申明并定义它继承自Animal类,如:
1
|
class Penguin extends Animal {
|
2
|
|
3
|
}
|
4
|
|
5
|
$tux = new Penguin;
|
6
|
echo $tux ->created;
|
如果我们定义一个构造方法在Penguin类中,然后Penguin对象将会运行当它被实例化后。由于并没有构造方法,PHP 会参考父类方法定义 信息来使用它因此我们能覆盖父类方法,或者不,在我们的新类中-很便利。
__destruct
你发现文件句柄也是构造器一部分吗?当我们使用完一个对象时真不想把事情放一边,因此析构方法做着与构造方法相反的事情。当对象被销毁时,析构方法会运行,或者明确的说当我们不再使用它时,php会为我们清理掉。Animal类中,我们的析构方法像这样,如:
01
|
class Animal{
|
02
|
|
03
|
public function __construct() {
|
04
|
$this ->created = time();
|
05
|
$this ->logfile_handle = fopen ( '/tmp/log.txt' , 'w' );
|
06
|
}
|
07
|
|
08
|
public function __destruct() {
|
09
|
fclose( $this ->logfile_handle);
|
10
|
}
|
11
|
}
|
析构器让我们关闭任何额外的资源比如被使用过的对象。在php中由于我们有这样运行时间短的脚本(留意在更新的php版本中增强的垃圾回收机制),通常讨论内存溢出根本不需要。然而它仍是好的推行方法来清理而且总体上让程序运行起来更高效。
__get
这个魔术方法是一个非常灵巧的小技巧 - 它使实际上不存在的属性如同存在一半。让我们举个小企鹅的例子:
01
|
class Penguin extends Animal {
|
02
|
|
03
|
public function __construct( $id ) {
|
04
|
$this ->getPenguinFromDb( $id );
|
05
|
}
|
06
|
|
07
|
public function getPenguinFromDb( $id ) {
|
08
|
// elegant and robust database code goes here
|
09
|
}
|
10
|
}
|
现在,如果我们的小企鹅有一个 "name" 属性,而在此之后加载的属性为 "age",那么我们可以这样处理:
1
|
$tux = new Penguin(3);
|
2
|
echo $tux ->name . " is " . $tux ->age . " years old\n" ;
|
然而,设想一下,后端数据库或数据供应者发生了改变,"name"没有了,变味了"username"。并且设想这是一个非常复杂的应用,而需要修改的调用"name"的地方非常多。我们可以使用 __get 方法,使得"name"属性如同存在一样:
01
|
class Penguin extends Animal {
|
02
|
|
03
|
public function __construct( $id ) {
|
04
|
$this ->getPenguinFromDb( $id );
|
05
|
}
|
06
|
|
07
|
public function getPenguinFromDb( $id ) {
|
08
|
// elegant and robust database code goes here
|
09
|
}
|
10
|
|
11
|
public function __get( $field ) {
|
12
|
if ( $field == 'name' ) {
|
13
|
return $this ->username;
|
14
|
}
|
15
|
}
|
这并不是编写整个系统的好方法,因为它会让调试工作变得更困难,但它是一个非常有价值的工具。它允许如同属性一样使用或者展示需要经过计算的数据,以及无数我都想不到的地方。
__set
那么,我们将所有对 $this->name 的调用都更改为返回 $this->username的值,那么,如果我们想要设置这个值呢?也许我们有一个账户界面允许用户修改他们的名字。这时我们就需要 __set 方法的帮助了,举例说明:
01
|
class Penguin extends Animal {
|
02
|
|
03
|
public function __construct( $id ) {
|
04
|
$this ->getPenguinFromDb( $id );
|
05
|
}
|
06
|
|
07
|
public function getPenguinFromDb( $id ) {
|
08
|
// elegant and robust database code goes here
|
09
|
}
|
10
|
|
11
|
public function __get( $field ) {
|
12
|
if ( $field == 'name' ) {
|
13
|
return $this ->username;
|
14
|
}
|
15
|
}
|
16
|
|
17
|
public function __set( $field , $value ) {
|
18
|
if ( $field == 'name' ) {
|
19
|
$this ->username = $value ;
|
20
|
}
|
21
|
}
|
22
|
}
|
这样,我们就针对大量的调用伪造对象的属性,正如我说的,这并不是一个正统的方法,但却是一个很有用的技巧,值得记住。
__call
这里有两种近似的方法,我并没有单独列出来,而是一起说明。一个是 _call 方法,如果定义,它将在调用未定义过的方法时被调用;另一个是 _callStatic 方法,工作方式与第一个相同,但却是在调用未定义的静态方法时生效(PHP 5.3 加入).通常我使用 __call 进行友善的错误处理,这在需要别人整合调用你的方法的库代码中非常有用。例如,如果一段脚本拥有一个企鹅对象,名为 $penguin ,它包含一个 $penguin->speak() 方法...假设 speak() 方法没有定义,那么正常情况下我们会看到:
PHP Fatal error: Call to undefined method Penguin::speak() in ...
通过定义 __call 方法,我们可以使用一些更友善的提示信息来代替 PHP 的错误提示:
01
|
class Animal {
|
02
|
}
|
03
|
class Penguin extends Animal {
|
04
|
|
05
|
public function __construct( $id ) {
|
06
|
$this ->getPenguinFromDb( $id );
|
07
|
}
|
08
|
|
09
|
public function getPenguinFromDb( $id ) {
|
10
|
// elegant and robust database code goes here
|
11
|
}
|
12
|
|
13
|
public function __get( $field ) {
|
14
|
if ( $field == 'name' ) {
|
15
|
return $this ->username;
|
16
|
}
|
17
|
}
|
18
|
|
19
|
public function __set( $field , $value ) {
|
20
|
if ( $field == 'name' ) {
|
21
|
$this ->username = $value ;
|
22
|
}
|
23
|
}
|
24
|
|
25
|
public function __call( $method , $args ) {
|
26
|
echo "unknown method " . $method ;
|
27
|
return false;
|
28
|
}
|
29
|
}
|
这将捕获的错误并回应。在实际应用中,更合适的方法是依据你的需要纪录消息日志·,将用户重定向,或者抛出一个异常,但概念是相同的。在这里你可以处理任何你需要处理的不当调用,你可以检测方法的名称,并一一处理——例如,你可以同上面我们重命名属性一些样重命名方法。
__sleep
__sleep()方法会被调用当对象被序列化后,并允许你处理序列化。这有各种各样的程序,一个很好的例子如果一个对象包含某种类型的指针,例如文件句柄或引用另一个对象。当对象被序列化然后解序列化,这些引用类型是无用的,因为这些类型的引用的目标可能不再存在或有效。因此,最好是来取消这些信息在存储它们之前。
__wakeup
__wakeup()是与__sleep()方法相反的,允许您更改对象解序列化的行为。和__sleep()一起使用,可以用来恢复被删除的句柄和对象当对象被序列化时。一个很好的例子程序是数据库句柄被取消设置当该项被序列化,然后恢复到当前配置中设置项目时,解序列化一个数据库句柄。
__clone
我们看过一个使用clone关键字的例子,在我的介绍从入门到oop的第二部分,创建对象的副本,而不是有两个变量指向同一个实际的数据。在一个类中重写此方法,我们可以观察发生了什么当在对象上使用clone关键字时,。虽然这是不是我们每一天能遇到的,一个漂亮的用例是创建一个真正的单例模式通过添加private访问修饰符给这个方法。
__toString
无疑把最好的始终留到最后,__toString方法是一个非常方便的附加方法对于我们的工具包。该方法可以声明覆盖对象的行为,当作为一个字符串输出时,例如,当它被输出时。如果你想能输出对象到模板中,你可以使用此方法来控制输出结果。让我们再来看看在Penguin类中:
01
|
class Penguin {
|
02
|
|
03
|
public function __construct( $name ) {
|
04
|
$this ->species = 'Penguin' ;
|
05
|
$this ->name = $name ;
|
06
|
}
|
07
|
|
08
|
public function __toString() {
|
09
|
return $this ->name . " (" . $this ->species . ")\n" ;
|
10
|
}
|
11
|
}
|
在适当的位置,输出该对象通过调用echo输出它,如:
1
|
$tux = new Penguin( 'tux' );
|
2
|
echo $tux ;
|
我不常常使用这种捷径,但是知道它的存在是很有用的。
更多魔术方法
10、__invoke(PHP 5.3.0以上版本有效)
当尝试以调用函数的方式调用一个对象时,__invoke 方法会被自动调用。
11、__callStatic(PHP 5.3.0以上版本有效)
它的工作方式类似于__call() 魔术方法,__callStatic() 是为了处理静态方法调用。
PHP 确实加强了对 __callStatic() 方法的定义;它必须是公共的,并且必须被声明为静态的。同样,__call() 魔术方法必须被定义为公共的,所有其他魔术方法都必须如此...
12.__debuginfo
当调用var_dump()打印对象时被调用(当你不想打印所有属性)适用于PHP5.6版本
更多参考 http://php.net/manual/zh/language.oop5.magic.php#object.invoke , 列出的所有的魔术方法(是的。不仅仅是文中所列出的,我仅仅选出那些我认为最好开始学习的)如果你想了解其他请仔细查看...
PHP中的12个魔术方法相关推荐
- 魔术方法php,PHP中常用的魔术方法
我们在PHP中经常用到魔术方法,像构造方法,析构方法等等魔术变量,下面总结一下一些常用的魔术变量: __construct(),__destruct(),__clone(),__autoload(), ...
- PHP5中的魔术方法
一. __construct(),类的构造函数 php中构造方法是对象创建完成后第一个被对象自动调用的方法.在每个类中都有一个构造方法,如果没有显示地声明它,那么类中都会默认存在一个没有参数且内容为空 ...
- OWASP TOP 10(六)反序列化漏洞(序列化和反序列化、漏洞原理、PHP中的序列化和反序列化、魔术方法、Typecho_v1.0中的反序列化漏洞)
文章目录 反序列化漏洞 一.概述 1. 序列化和反序列化 2. 序列化的目的 二.PHP中的序列化与反序列化 1. 概述 2. 示例序列化与反序列化 3. 反序列化漏洞 - PHP中的魔术方法 - T ...
- PHP面向对象常见的关键字和魔术方法
在PHP5的面向对象程序设计中提供了一些常见的关键字,用来修饰类.成员属性或成员方法,使他们具有特定的功能,例如final.static.const等关键字.还有一些比较实用的魔术方法,用来提高类或对 ...
- PHP十六个魔术方法
PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __construct(),类的构造函数 __destruct ...
- php超全局变量,魔术常量,魔术方法
整理了下关于php的基础知识,参考了些资料,如下: 超全局变量 超全局变量 - 超全局变量是在全部作用域中始终可用的内置变量: $GLOBALS $GLOBALS - 引用全局作用域中可用的全部变量 ...
- mysql 魔术设置_PHP之十六个魔术方法详细介绍
PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __construct(),类的构造函数 __destruct ...
- python描述符魔术方法_Python类型转换的魔术方法详解
本文讨论python中将某个复杂对象转换为简单对象或数据类型的常用魔术放啊,这些在编程中是十分有用的. 1.__str__方法. 在讲解本方法前我们先打开一个jupyter notebook,随意创建 ...
- Python高级专题 - 类型转换的魔术方法
Python 类型转换的魔术方法 jcLee95 的 CSDN 博客 本文讨论python中将某个复杂对象转换为简单对象或数据类型的常用魔术放啊,这些在编程中是十分有用的. 邮箱 :291148484 ...
最新文章
- Asp.Net页面执行流程分析
- .NET 网站自动登录
- 查看 Oracle 是32位还是64位的方法
- spring之java配置(springboot推荐的配置方式)
- 如何在7分钟内黑掉40家网站?
- oracle 数据库的非指令备份方法
- LeetCode 594. Longest Harmonious Subsequence
- 【题解】Luogu P5294 [HNOI2019]序列
- ODM操作MongoDB
- 智能生活 App SDK 开发入门教程
- day17.什么是堆栈
- 图像修复论文阅读笔记-----Globally and Locally Consistent Image Completion
- 优漫动游平面设计的形式美
- HDMI采集卡芯片方案
- 工厂管理系统该如何选?5款主流的工厂管理软件全测评!
- Skeleton Screen -- 骨架屏
- 化妆品电商平台数据分析报告
- CA机构介绍(Certificate Authority 域名SSL证书颁发机构)
- 计算机网络之应用层-Internet电子邮件
- iOS设计模式之MVC
热门文章
- 转 Android视频播放软解与硬解的区别
- Ventuz学习笔记之-Container预制体等间距排列复制
- 数据结构:队列queue的实现及功能
- Virtualbox+Vagrant搭建linux虚拟机并搭建easySwoole框架
- 夺命雷公狗—玩转SEO---55---页面去重原理
- TMS 和 ERP 对3PL企业的核心竞争力的影响分析
- 存储程序让计算机自动化,“存储程序控制”思想是冯·诺依曼在哪年提出的?
- 中资企业,外派工作招聘
- 网络安全——常用的数据加密算法介绍
- 华硕笔记本win10系统wlan图标不见了