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 相关文章推荐
一个简单的自动发送邮件系统(三)
Oct 09 PHP
PHP Error与Logging函数的深入理解
Jun 03 PHP
PHP管理依赖(dependency)关系工具 Composer的自动加载(autoload)
Aug 18 PHP
php中getservbyport与getservbyname函数用法实例
Nov 18 PHP
php使用cookie保存登录用户名的方法
Jan 26 PHP
php创建无限级树型菜单
Nov 05 PHP
thinkphp在php7环境下提示Cannot use ‘String’ as class name as it is reserved的解决方法
Sep 30 PHP
PHP简单读取xml文件的方法示例
Apr 20 PHP
使用PHPExcel实现数据批量导出为excel表格的方法(必看)
Jun 09 PHP
thinkphp5 加载静态资源路径与常量的方法
Dec 24 PHP
PHP中Static(静态)关键字功能与用法实例分析
Apr 05 PHP
thinkPHP事务操作简单案例分析
Oct 17 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编程风格规范分享
2014/01/15 PHP
PHP针对JSON操作实例分析
2015/01/12 PHP
深入解析PHP中foreach语句控制数组循环的用法
2015/11/30 PHP
PHP各种常见经典算法总结【排序、查找、翻转等】
2019/08/05 PHP
js 实现打印网页中定义的部分内容的代码
2010/04/01 Javascript
jquery validate使用攻略 第四步
2010/07/01 Javascript
让JavaScript拥有类似Lambda表达式编程能力的方法
2010/09/12 Javascript
javascript与jquery中跳出循环的区别总结
2013/11/04 Javascript
BootStrap Validator对于隐藏域验证和程序赋值即时验证的问题浅析
2016/12/01 Javascript
AngularJS select设置默认值的实现方法
2017/08/25 Javascript
JS函数节流和函数防抖问题分析
2017/12/18 Javascript
vue如何判断dom的class
2018/04/26 Javascript
利用JavaScript缓存远程窃取Wi-Fi密码的思路详解
2018/11/05 Javascript
微信小程序引入VANT组件的方法步骤
2019/09/19 Javascript
JS中this的4种绑定规则详解
2020/02/04 Javascript
JavaScript 替换所有匹配内容及正则替换方法
2020/02/12 Javascript
[03:37]2015国际邀请赛第四日现场精彩集锦
2015/08/08 DOTA
Python Django切换MySQL数据库实例详解
2019/07/16 Python
Django实现文件上传下载
2019/10/06 Python
python实现五子棋游戏(pygame版)
2020/01/19 Python
TensorFlow dataset.shuffle、batch、repeat的使用详解
2020/01/21 Python
在ipython notebook中使用argparse方式
2020/04/20 Python
简单了解Django项目应用创建过程
2020/07/06 Python
Wojas罗马尼亚网站:波兰皮鞋品牌
2018/11/01 全球购物
成语的广告词
2014/03/19 职场文书
小学学校评估方案
2014/06/08 职场文书
政风行风建设责任书
2014/07/23 职场文书
国际贸易系求职信
2014/08/09 职场文书
员工试用期自我评价
2014/09/18 职场文书
上课说话检讨书500字
2014/11/01 职场文书
银行反洗钱宣传活动总结
2015/05/08 职场文书
结婚典礼致辞
2015/07/28 职场文书
《孙子兵法》:欲成大事者,需读懂这些致胜策略
2019/08/23 职场文书
使用 JavaScript 制作页面效果
2021/04/21 Javascript
MySQL库表太大怎么办? 数据库分库分表项目实践
2022/04/11 MySQL
不想升级Win11?教你彻底锁定老版Windows系统的方法(附下载地址)
2022/09/23 数码科技