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 相关文章推荐
经典的PHPer为什么被认为是草根?
Apr 02 PHP
PHP获取文件绝对路径的代码(上一级目录)
May 29 PHP
php记录代码执行时间(实现代码)
Jul 05 PHP
php session劫持和防范的方法
Nov 12 PHP
php fsockopen解决办法 php实现多线程
Jan 20 PHP
最常用的8款PHP调试工具
Jul 06 PHP
PHP生成树的方法
Jul 28 PHP
Yii2 RESTful中api的使用及开发实例详解
Jul 06 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
Jun 13 PHP
PHP实现微信提现功能
Sep 30 PHP
PHP检测一个数组有没有定义的方法步骤
Jul 20 PHP
TP5框架安全机制实例分析
Apr 05 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中var_export与var_dump的区别分析
2010/08/21 PHP
php添加文章时生成静态HTML文章的实现代码
2013/02/17 PHP
php不使用插件导出excel的简单方法
2014/03/04 PHP
PHPStrom中实用的功能和快捷键大全
2015/09/23 PHP
浅谈PHP链表数据结构(单链表)
2016/06/08 PHP
PHP实现图片的等比缩放和Logo水印功能示例
2017/05/04 PHP
php实现的中秋博饼游戏之绘制骰子图案功能示例
2017/11/06 PHP
CSS常用网站布局实例
2008/04/03 Javascript
javascript parseInt与Number函数的区别
2010/01/21 Javascript
浅析Node.js查找字符串功能
2014/09/03 Javascript
JS实现星星评分功能实例代码(两种方法)
2016/06/09 Javascript
js 弹出对话框(遮罩)透明,可拖动的简单实例
2016/07/11 Javascript
基于WebUploader的文件上传js插件
2016/08/19 Javascript
简单实现js无缝滚动效果
2017/02/05 Javascript
Vue.js仿微信聊天窗口展示组件功能
2017/08/11 Javascript
详解使用React进行组件库开发
2018/02/06 Javascript
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
2019/02/14 jQuery
详解Vue项目引入CreateJS的方法(亲测可用)
2019/05/30 Javascript
通过实例了解js函数中参数的传递
2019/06/15 Javascript
微信小程序实现锚点功能
2019/11/20 Javascript
Vue extend的基本用法(实例详解)
2019/12/09 Javascript
vue:el-input输入时限制输入的类型操作
2020/08/05 Javascript
跟老齐学Python之开始真正编程
2014/09/12 Python
python通过pil模块将raw图片转换成png图片的方法
2015/03/16 Python
Python操作Excel之xlsx文件
2017/03/24 Python
详解使用python的logging模块在stdout输出的两种方法
2017/05/17 Python
Python实现通过解析域名获取ip地址的方法分析
2019/05/17 Python
Python3 main函数使用sys.argv传入多个参数的实现
2019/12/25 Python
用Python自动清理系统垃圾的实现
2021/01/18 Python
俄罗斯护发和专业化妆品购物网站:Hihair
2019/09/28 全球购物
日本即尚网:JSHOPPERS.com(支持中文)
2019/12/03 全球购物
幼师岗位求职简历的自荐信格式
2013/09/21 职场文书
2014年团支部年度工作总结
2014/12/24 职场文书
工作收入证明模板
2015/06/12 职场文书
红十字会救护培训简讯
2015/07/20 职场文书
vue Element-ui表格实现树形结构表格
2021/06/07 Vue.js