当前位置: 首页 > 编程笔记 >

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

史默
2023-03-14
本文向大家介绍PHP获取类私有属性的3种方法,包括了PHP获取类私有属性的3种方法的使用技巧和注意事项,需要的朋友参考一下

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

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

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引入的bindTo。call和bindTo的用法示例如下:

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获取类私有属性的资料请关注小牛知识库其它相关文章!

 类似资料:
  • 在 Python 的面向对象编程中,私有属性是只能在类的实例方法中访问的属性,不允许在外界访问私有属性。 1. 私有属性的定义 1.1 定义 在属性名称前加上前缀 __,表示该属性为私有属性,示例代码如下: class Object: def method(self): self.__private_attribute = 123 在第 3 行,创建一个私有属性 __pr

  • 本文向大家介绍PHP获取对象属性的三种方法实例分析,包括了PHP获取对象属性的三种方法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP获取对象属性的三种方法。分享给大家供大家参考,具体如下: 今天查看yii源码,发现yii\base\Model中的attribute()方法是通过反射获取对象的public non-static属性。记得以前看到的代码都是用get_object

  • 问题内容: 是否可以在ES6类中创建私有属性? 这是一个例子。如何防止访问? 问题答案: 专用字段(和方法)正在ECMA标准中实现。您可以立即从[babel 7和Stage3预设开始使用它们。

  • 本文向大家介绍PHP获取MySql新增记录ID值的3种方法,包括了PHP获取MySql新增记录ID值的3种方法的使用技巧和注意事项,需要的朋友参考一下 一、使用语句:   使用此方法得到的是 id最大的值,确为最后一个值,但当多链接线程时,这个最大的id并不一定是我们插入数据的自增id值,因此不适用于多线程。 二,使用函数:msyql_insert_id(); 在PHP中,经常需要把插入数据库中的

  • 本文向大家介绍Java获取随机数的3种方法,包括了Java获取随机数的3种方法的使用技巧和注意事项,需要的朋友参考一下 主要介绍了Java获取随机数的3种方法,主要利用random()函数来实现 方法1 (数据类型)(最小值+Math.random()*(最大值-最小值+1))例: 从1到10的int型随数 方法2 获得随机数 通过java.Math包的random方法得到1-10的int随机数

  • 问题内容: 如何在基于字符串的PHP中获取属性?我给它打电话。那是什么? 就像… 问题答案: 像这样 或者,如果您可以控制该类,请实现ArrayAccess接口,然后执行此操作

  • 问题内容: 那么是否可以仅针对最特定的类获取属性的字典/列表?到目前为止,我正在使用 但这也将给我提供超类中定义的服装。有什么办法可以避免这种情况? 问题答案: 摘自python文档 类具有由字典对象实现的名称空间。类属性引用将转换为此字典中的查找,例如Cx被转换为C . dict [“ x”](尽管特别是对于新式类,有许多允许使用其他方式定位属性的钩子)。如果找不到属性名称,则在基类中继续搜索属

  • 我花了很长时间研究这个问题。但我还是没有找到解决办法。请帮我解决这个问题。我有一个JSP文件,并在应用程序中使用struts。当我尝试在浏览器中加载页面时,它会抛出此错误。 一切都很好。也没有区分大小写的问题。但是这个代码不起作用。请帮我解决这个问题。 JSP: 还有我的班级档案