• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    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引入的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获取类私有属性的资料请关注脚本之家其它相关文章!

    您可能感兴趣的文章:
    • PHPUnit测试私有属性和方法功能示例
    • PHP实现在对象之外访问其私有属性private及保护属性protected的方法
    上一篇:php实现图片压缩处理
    下一篇:PHP反射基础知识回顾
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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