本节书摘来自华章社区《PHP精粹:编写高效PHP代码》一书中的第1章,第1.8节更多神奇的方法,作者:(美) Davey Shafik,更多章节内容可以访问云栖社区“华章社区”公众号查看
1.8 更多神奇的方法
本章已介绍了一些神奇方法。在表1.1中快速回顾一下这些方法。
当在一个类中定义这些函数时,可以定义当这些事件发生时会引发什么。没有这些函数的话,类将显现为默认行为,而这些常常都是需要的。PHP另外还有一些神奇方法,在本节中我们将看到一些使用最频繁的方法。
1.8.1 使用__call()和__callStatic()方法
在关于访问修饰符的内容里,我们看到,对于__get()和__set()方法而言,__call()方法是一个天生的搭档。使用__get()和__set()方法处理不是真实存在的属性,__call()方法的作用与它们相同。当调用一个没有在类中声明的方法时,可以调用__call()方法代替声明一个方法。
我们已经使用过Courier类的ship()方法,但是如果我们想调用sendParcel()来实现相同的功能呢?当使用一些过时的系统时,通常依次更换现存系统的一部分。可以修改Courier类定义使其包含sendParcel()方法,还可以使用__call()方法,比如像这样:
所有这些魔法一定留下了机会让人们创建出代码精粹,不是任何普通人都能使用它们的!当使用__call()方法替代声明一个方法时,会让IDE自动生成方法名的功能失效。当检查一个类中是否存在一个函数时,该方法将无法显示,在调试时很难追踪错误所在。针对这种情况,即用老代码调用老的方法名,你可能认为这实际上是一种使函数不可见的特性—这种情况让我们更明白,我们今天所写的代码不可能使用到这种方式。
所有的软件设计都没有硬性的规定,但就类中的“伪装”方法而论,你确信无疑会有很多收获,因此你可以适度地使用这个功能。
除了__call()方法之外,从PHP 5.3开始,也有了__callStatic()。你期望它做什么它就会做什么。当创建一个静态方法以调用该类中不存在的一个方法时,可以使用__callStatic()方法。就像__call()方法一样,__callStatic()方法接受方法名和数组作为参数。
1.8.2 使用__toString()方法输出对象
你是否曾经尝试过对一个对象使用echo()方法?默认情况下,它只是简单地输出“Object”,作用并不大。可以使用神奇的_toString()方法来改变这种行为,或者,让Courier类像示例一样输出一个更好的描述,可以这样输入代码:
可以序列化一个对象,也可以在系统中反序列化(unserialize),该系统中类定义的对象是可用的。但是有时我们不想序列化一些对象的属性,因为在其他的环境中它们会失效。资源就是一个很好的例子;一个文件指针在稍后一点或其他的平台上反序列化将毫无意义。
为了帮助我们解决这个问题,PHP提供了__sleep()和__wakeup()方法,它们分别在序列化和反序列化时调用。利用这些方法决定哪种属性可以序列化,且当对象是woken时,可以填充任何没有存储的对象。利用这种方式可以迅速地设计类。例如,如何在类中添加一个文件句柄以记入错误日志呢?
像这样使用神奇的方法,可以避免在序列化资源或链接到其他导致失效的对象或项目时犯错。这使我们能够安全地存储对象,并且在需要时适应特殊的需求。