上文中介绍了非常常用并且也是面试时的热门魔术方法,而这篇文章中的所介绍的或许并不是那么常用,但绝对是加分项。当你能准确地说出这些方法及作用的时候,相信对方更能对你刮目相看。

__sleep()与__wakeup()

字面上的意思很好玩,睡觉和起床。它们分别对应着serialize()和unserialize()方法,也就是序列化和反序列化时会触发这两个魔术方法。

这里需要注意的是,__sleep()需要返回一个数组,而这个数组对应着类中的属性名。通常来说,它们可以在序列化前进行数据清理工作,或者反序列化前进行数据的预处理工作。比如序列化前关闭数据库连接或者反序列化前打开数据库连接。

public function __sleep()
{
echo '===sleep===' . PHP_EOL;
echo '调用serialize()时来找我,先睡一会的' . PHP_EOL;
echo '===unset===' . PHP_EOL;
return ['a'];
} public function __wakeup()
{
echo '===wakeup===' . PHP_EOL;
echo '调用unserialize()时来找我,起床吧' . PHP_EOL;
echo '===wakeup===' . PHP_EOL;
}

__toString()

顾名思义,这个方法通过返回一个字符串,实现对象的打印。如果没有实现这个方法,我们直接使用echo是无法打印对象的,会报错。当实现了这个魔术方法后,直接使用echo或者print等方法就可以进入这个魔术方法中,并打印出该方法中返回的内容。

public function __toString()
{
echo '===toString===' . PHP_EOL;
echo '调用echo、print时会使用我' . PHP_EOL;
echo '===toString===' . PHP_EOL;
return '打印出来看看吧';
}

当然,它也能实现对象转换到字符串,如在字符串拼接的时候,如:$obj = new Object(); $a = 'this is ' . $obj;这样使用。

__invoke()

很有意思的一个魔术方法,它的作用是将对象当做方法使用时会调用这个魔术方法。什么意思呢?比如:$obj = new Object();,然后直接$obj();

这时,就会进入这个魔术方法。那么有什么用呢?对于闭包以及反射来说,这个魔术方法有不可替代的作用。将来我们会在别的文章中进行详细说明。

public function __invoke()
{
echo '===invoke===' . PHP_EOL;
echo '把类当方法使用时就进这里了' . PHP_EOL;
echo '===invoke===' . PHP_EOL;
}

__clone()

使用clone关键字进行对象的复制时,就会调用这个魔术方法。其实就是原型模式的实现。在原型模式的相关文章中我们再来详细说明。

public function __clone()
{
echo '===clone===' . PHP_EOL;
echo '复制类的时候我就发挥作用了' . PHP_EOL;
echo '===clone===' . PHP_EOL;
}

__set_state()与__debugInfo()

真的是神奇的PHP语法,最后这两个魔术方法一个是用的下划线命名,一个是用的小驼峰。实在无力吐槽~~

这两个方法对应的是var_export()和var_dump()方法在使用时的调用。一般是在调试时使用,其实非常类似于__toString()方法。

public static function __set_state($an_array)
{
echo '===set_state===' . PHP_EOL;
echo '使用var_export()的时候使用调用我哦' . PHP_EOL;
echo '===set_state===' . PHP_EOL;
$m = new PHPMagic();
$m->var1 = 111;
$m->var2 = 222;
return $m;
} public function __debugInfo()
{
echo '===debugInfo===' . PHP_EOL;
echo '使用var_dump()的时候就是我来啦' . PHP_EOL;
echo '===debugInfo===' . PHP_EOL;
return [
'var1' => $this->var1,
'var2' => $this->var2,
];
}

通过两篇文章,我们熟悉了PHP所定义的这些魔术方法。在这里需要特别注意的是,PHP中将所有以__两个下划线开头的方法做为魔术方法的保留命名。所以在定义类方法的时候,不要使用两个下划线开头的方法名。

文档参考:https://www.php.net/manual/zh/language.oop5.magic.php

完整代码:https://github.com/zhangyue0503/php/blob/master/newblog/PHPMagic.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

最新文章

  1. 【jq】c#零基础学习之路(4)抽象类和密封
  2. cocos布局分析
  3. android自定义RadioGroup实现可以添加多种布局
  4. "渴了么"用户场景分析
  5. 二手奢侈品电商Vestiaire Collective融资2000万美元
  6. [置顶] API相关工作过往的总结之整体介绍
  7. html页面显示服务器时间
  8. azkaben任务调度器
  9. Scala减少代码重复
  10. oracle非正常退出后重启实例
  11. 不转实体直接获取Json字符串中某个字段的值
  12. Java正则中为什么反斜线"\"需要用“\\\\”表示,原因详解。
  13. 18-09-19 关于outlook的使用
  14. Python官方操作Excel文档
  15. ADHOC Report 配置
  16. spring boot: spring-data-jpa (Repository/CrudRepository) 数据库操作, @Entity实体类持久化
  17. 图像处理和OpenCV初步
  18. JVM监控工具用法指导
  19. [LeetCode]Maximum Subarray题解
  20. 180615-精度计算BigDecimal

热门文章

  1. Vue CLI安装报错 npm ERR! Exit handler never called!
  2. Pikahu-SQL注入模块和sqlmap经典用法
  3. NOIP 模拟 $11\; \rm english$
  4. 【编程语言】Matlab 学习记录
  5. idea的properties文件乱码问题解决
  6. mysql 数据库 分表后 怎么进行分页查询?Mysql分库分表方案?
  7. 在C#中使用C++编写的类——用托管C++进行封装
  8. 【C++】 四种强制类型转换(static_cast 与 dynamic_cast 的区别!)
  9. Maven解决依赖冲突
  10. Java 中 常用API概述之 Math, Object, String,StringBuffer类,Arrays,Integer类