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 URL编码解码函数代码
Mar 10 PHP
PHP 数组排序方法总结 推荐收藏
Jun 30 PHP
phpadmin如何导入导出大数据文件及php.ini参数修改
Feb 18 PHP
php以post形式发送xml的方法
Nov 04 PHP
PHP微信开发之微信消息自动回复下所遇到的坑
May 09 PHP
CodeIgniter框架验证码类库文件与用法示例
Mar 18 PHP
Laravel中encrypt和decrypt的实现方法
Sep 24 PHP
php中各种定义变量的方法小结
Oct 18 PHP
php利用云片网实现短信验证码功能的示例代码
Nov 18 PHP
浅谈PHP中pack、unpack的详细用法
Mar 12 PHP
PHP命名空间简单用法示例
Dec 28 PHP
Laravel统计一段时间间隔的数据方法
Oct 09 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
MOTOROLA 摩托罗拉 MODEL 66-XI五灯中波收音机
2021/03/02 无线电
一个PHP的String类代码
2010/04/20 PHP
PHP批量上传图片的具体实现方法介绍.
2014/02/26 PHP
PHP包含文件函数include、include_once、require、require_once区别总结
2014/04/05 PHP
函数中使用require_once问题深入探讨 优雅的配置文件定义方法推荐
2014/07/02 PHP
yii用户注册表单验证实例
2015/12/26 PHP
PHP 输出缓冲控制(Output Control)详解
2016/08/25 PHP
让插入到 innerHTML 中的 script 跑起来的实现代码
2006/07/01 Javascript
Javascript实现CheckBox的全选与取消全选的代码
2010/07/20 Javascript
jQuery学习笔记之jQuery.extend(),jQuery.fn.extend()分析
2014/06/09 Javascript
node.js中的fs.lchmodSync方法使用说明
2014/12/16 Javascript
JavaScript中计算网页中某个元素的位置
2015/06/10 Javascript
Fullpage.js固定导航栏-实现定位导航栏
2016/03/17 Javascript
JQuery之proxy实现绑定代理方法
2016/08/01 Javascript
有关suggest快速删除后仍然出现下拉列表的bug问题
2016/12/02 Javascript
详解AngularJS 模块化
2017/06/14 Javascript
解决Vue 浏览器后退无法触发beforeRouteLeave的问题
2017/12/24 Javascript
vue和webpack安装命令详解
2018/06/15 Javascript
js指定日期增加指定月份的实现方法
2018/12/19 Javascript
html2canvas属性和使用方法以及如何使用html2canvas将HTML内容写入Canvas生成图片
2020/01/12 Javascript
node.js基础知识汇总
2020/08/25 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
2021/02/05 Javascript
[54:51]Ti4 冒泡赛第二轮LGD vs C9 3
2014/07/14 DOTA
Python Socket使用实例
2017/12/18 Python
Python多线程中阻塞(join)与锁(Lock)使用误区解析
2018/04/27 Python
详解多线程Django程序耗尽数据库连接的问题
2018/10/08 Python
python requests更换代理适用于IP频率限制的方法
2019/08/21 Python
在OpenCV里使用特征匹配和单映射变换的代码详解
2019/10/23 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
详解Canvas 实现炫丽的粒子运动效果(粒子生成文字)
2018/02/01 HTML / CSS
HTML5 Canvas 实现K线图的示例代码
2019/12/23 HTML / CSS
向全球直邮输送天然健康产品:iHerb.com
2020/05/03 全球购物
办理退休介绍信
2014/01/09 职场文书
电焊工岗位工作职责
2014/07/09 职场文书
2016年清明节寄语
2015/12/04 职场文书
《怀念母亲》教学反思
2016/02/19 职场文书