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
PHP4(windows版本)中的COM函数
Oct 09 PHP
桌面中心(二)数据库写入
Oct 09 PHP
APMServ使用说明
Oct 23 PHP
PHP 反射机制实现动态代理的代码
Oct 22 PHP
第三章 php操作符与控制结构代码
Dec 30 PHP
php中的动态调用实例分析
Jan 07 PHP
如何解决phpmyadmin导入数据库文件最大限制2048KB
Oct 09 PHP
Yii2配置Nginx伪静态的方法
May 05 PHP
PHP实现的注册,登录及查询用户资料功能API接口示例
Jun 06 PHP
浅谈Laravel中的一个后期静态绑定
Aug 11 PHP
php微信开发之关键词回复功能
Jun 13 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
ThinkPHP使用smarty模板引擎的方法
2014/07/01 PHP
php合并数组中相同元素的方法
2014/11/13 PHP
typecho插件编写教程(一):Hello World
2015/05/28 PHP
PHP常见数组函数用法小结
2016/03/21 PHP
PHPExcel简单读取excel文件示例
2016/05/26 PHP
laravel框架数据库操作、查询构建器、Eloquent ORM操作实例分析
2019/12/20 PHP
将jQuery应用于login页面的问题及解决
2009/10/17 Javascript
基于jQuery的弹出框插件
2012/03/18 Javascript
一个简单的瀑布流效果(主体形式自写)
2013/05/27 Javascript
js获取网页可见区域、正文以及屏幕分辨率的高度
2014/05/15 Javascript
Javascript表单验证要注意的事项
2014/09/29 Javascript
jquery实现聚光灯效果的方法
2015/02/06 Javascript
jQuery实现的调整表格行tr上下顺序
2016/01/10 Javascript
jQuery实现TAB选项卡切换特效简单演示
2016/03/04 Javascript
jQuery web 组件 后台日历价格、库存设置的代码
2016/10/14 Javascript
js读取json文件片段中的数据实例
2017/03/09 Javascript
详解自定义ajax支持跨域组件封装
2018/02/08 Javascript
vue 项目 iOS WKWebView 加载
2019/04/17 Javascript
vue开发拖拽进度条滑动组件
2019/09/21 Javascript
vue下canvas裁剪图片实例讲解
2020/04/16 Javascript
解决vue watch数据的方法被调用了两次的问题
2020/11/07 Javascript
如何在Express4.x中愉快地使用async的方法
2020/11/18 Javascript
用于统计项目中代码总行数的Python脚本分享
2015/04/21 Python
python实现根据主机名字获得所有ip地址的方法
2015/06/28 Python
详解用Python处理HTML转义字符的5种方式
2017/12/27 Python
Flask实现跨域请求的处理方法
2018/09/27 Python
Django csrf 两种方法设置form的实例
2019/02/03 Python
使用 Python 写一个简易的抽奖程序
2019/12/08 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
2020/06/08 Python
英国手工布艺沙发在线购买:Sofas & Stuff
2018/03/02 全球购物
法国高保真音响和家庭影院商店:Son Video
2019/04/26 全球购物
会计专业自荐信
2013/12/02 职场文书
生产部厂长职位说明书
2014/03/03 职场文书
党员查摆剖析材料
2014/10/10 职场文书
农贸批发市场管理制度
2015/08/07 职场文书
深入理解mysql事务隔离级别和存储引擎
2022/04/12 MySQL