PHP获取类私有属性的3种方法


Posted in PHP onSeptember 10, 2020

今天在推上看到一条获取PHP类私有属性的推文,感觉很有意思:

PHP获取类私有属性的3种方法

顺着推文联想,还有其他方式吗?经过自己的测试及网上答案,总结出三种方法:

1. 反射

反射可以获取类的详细信息,要获取私有属性的值,只需将对应属性的ReflectionProperty实例设置为可访问再取值即可。示例代码如下:

namespace tlanyan;

class Foo {
 private $bar = "Foo bar!";
}

// 获取反射类及反射属性
$class = new \ReflectionClass(Foo::class);
$property = $class->getProperty("bar");
// 设置属性可访问
$property->setAccessible(true);

$foo = new Foo;
// 获取对象属性值
// 注意:只能通过 ReflectionProperty 实例的 getValue 方法访问
// 不能这样直接访问: $foo->bar;
echo $property->getValue($foo), PHP_EOL:
// 输出: Foo bar!

本人之前写过“PHP回顾之反射”一文,比较详细的介绍了反射及用法,有兴趣的阅读参考。

2. 转换成数组

这种方法用将对象强制转换成数组,再通过键获取其值。示例代码如下:

class Foo {
 private $bar = "Foo bar!";
}

$foo = new Foo;
// 强制转型
$attrs = (array)$foo;
// 拼接key,注意 "\0" 不能改成单引号!
$key = "\0" . Foo::class . "\0" . "bar";
echo $attrs[$key], PHP_EOL;
// 输出: Foo bar!

上述代码中key的拼接方式比较诡异,key规则如下:

  1. public属性, key是 属性名;
  2. protected属性,key是 \0*\0属性名;
  3. private属性, key是 \0类名\0属性名。

注意 \0 是一个字符(不是两个),对应的ASCII码是数字0。编程时要用双引号将其引起来。不能使用单引号,否则转义失效,那就是两个字符。如果你有C语言基础,应该知道 \0 就是字符串的结束符。这个符号直接输出不会显示,但可以通过strlen或者ord让其现形:

foreach ($attrs as $key => $value) {
 echo "key:$key", ", key length:", strlen($key), ", ascii: ";
 for ($i = 0; $i < strlen($key); ++ $i) {
 echo ord($key[$i]), " "; 
 }
 echo PHP_EOL;
}
// 输出
// key:Foobar, key length:8, ascii: 0 70 111 111 0 98 97 114
// Foobar 有6个字符,加上两个不显示字符,所以长度是8

还需要注意拼接private属性时类名应该是 “完全限定类名” ,建议通过Foo::class的方式获取。

与强制转换成数组类似的另一种方法是serialize,但是serialize比较慢,并且序列化后的字符串更难辨认结构和处理,不建议使用。

3. 闭包

文章开头的推特截图已经展示了闭包的用法,其中call方法在PHP7中引入,另一个是PHP5.4引入的bindTocallbindTo的用法示例如下:

namespace tlanyan;

class Foo {
 private $bar = "Foo bar!";
}

$foo = new Foo;
// 闭包(匿名函数)是PHP5.3引入的功能
$closure = function() { return $this->bar; };
// PHP5.4起支持bindTo方法
$method = $closure->bindTo($foo, Foo::class);
echo $method(), PHP_EOL;

// PHP7引入call方法,可绑定this直接执行
echo $closure->call($foo), PHP_EOL;

bindTo方法的第二个参数注意传入对象的 “完全限定类名”,指示函数应该放置在该类的作用域下,从而可以访问私有属性。

总结

性能: 数组 > 反射 > 闭包

易用性: 闭包 > 数组 > 反射

推荐: 闭包 > 反射 > 数组

以上就是PHP获取类私有属性的3种方法的详细内容,更多关于PHP获取类私有属性的资料请关注三水点靠木其它相关文章!

PHP 相关文章推荐
PHP脚本的10个技巧(2)
Oct 09 PHP
php之对抗Web扫描器的脚本技巧
Oct 01 PHP
php win下Socket方式发邮件类
Aug 21 PHP
PHP写UltraEdit插件脚本实现方法
Dec 26 PHP
php class中self,parent,this的区别以及实例介绍
Apr 24 PHP
php 模拟get_headers函数的代码示例
Apr 27 PHP
PHP 冒泡排序 二分查找 顺序查找 二维数组排序算法函数的详解
Jun 25 PHP
phpstrom使用xdebug配置方法
Dec 17 PHP
PHP中list()函数用法实例简析
Jan 08 PHP
利用Homestead快速运行一个Laravel项目的方法详解
Nov 14 PHP
PHP中使用mpdf 导出PDF文件的实现方法
Oct 22 PHP
PHP实现二维数组按照指定的字段进行排序算法示例
Apr 23 PHP
php实现图片压缩处理
Sep 09 #PHP
如何在PHP中读写文件
Sep 07 #PHP
PHP延迟静态绑定使用方法实例解析
Sep 05 #PHP
PHP autoload使用方法及步骤详解
Sep 05 #PHP
PHP数组访问常用方法解析
Sep 05 #PHP
XAMPP升级PHP版本实现步骤解析
Sep 04 #PHP
php使用Swoole实现毫秒级定时任务的方法
Sep 04 #PHP
You might like
并发下常见的加锁及锁的PHP具体实现代码
2010/10/12 PHP
thinkPHP5实现数据库添加内容的方法
2017/10/25 PHP
php创建类并调用的实例方法
2019/09/25 PHP
window.location.reload()方法刷新页面弹出要再次显示该网页对话框
2013/04/24 Javascript
javascript中的变量作用域以及变量提升详细介绍
2013/10/24 Javascript
javascript调试过程中找不到哪里出错的可能原因
2013/12/16 Javascript
jquery仿搜索自动联想功能代码
2014/05/23 Javascript
jquery判断浏览器后退时候弹出消息的方法
2014/08/11 Javascript
js常用系统函数用法实例分析
2015/01/12 Javascript
JS实现横向与竖向两个选项卡Tab联动的方法
2015/09/27 Javascript
js+html5操作sqlite数据库的方法
2016/02/02 Javascript
深入理解jQuery事件绑定
2016/06/02 Javascript
从零开始学习Node.js系列教程一:http get和post用法分析
2017/04/13 Javascript
jQuery 实现双击编辑表格功能
2017/06/19 jQuery
vue实现点击展开点击收起效果
2018/04/27 Javascript
JavaScript设计模式之职责链模式应用示例
2018/08/07 Javascript
Node.js assert断言原理与用法分析
2019/01/04 Javascript
通过循环优化 JavaScript 程序
2019/06/24 Javascript
解析vue、angular深度作用选择器
2019/09/11 Javascript
javascript实现左右缓动动画函数
2020/11/25 Javascript
在Python中操作日期和时间之gmtime()方法的使用
2015/05/22 Python
TensorFlow深度学习之卷积神经网络CNN
2018/03/09 Python
pygame库实现俄罗斯方块小游戏
2019/10/29 Python
Python使用jpype模块调用jar包过程解析
2020/07/29 Python
Pycharm安装python库的方法
2020/11/24 Python
AmazeUI 等分网格的实现示例
2020/08/25 HTML / CSS
印度在线购买电子产品网站:Croma
2020/01/02 全球购物
梅西百货官网:Macy’s
2020/08/04 全球购物
教育科学研究生自荐信
2013/10/09 职场文书
开办加工厂创业计划书
2014/01/03 职场文书
收银员的岗位职责范本
2014/02/04 职场文书
园艺专业毕业生求职信
2014/09/02 职场文书
2014年业务工作总结
2014/11/17 职场文书
先进党员事迹材料
2014/12/24 职场文书
财务统计员岗位职责
2015/04/14 职场文书
tomcat正常启动但网页却无法访问的几种解决方法
2022/05/06 Servers