菜单开关

周梦康 发表于 2018-01-30 1193 次浏览

免费领取阿里云优惠券 我的直播 - 《PHP 进阶之路》

PHP 的反射能获取到私有成员吗?今天在封装一个工具的时候想到这个问题。
我知道 java 里面是可以的,setAccessible(true)就行,完整 demo https://mengkang.net/791.html

查看了手册,这块应该是参考的 java 设计的吧,基本类似

class Article {
    private $id;
    private $title;
    public $content;

    function __construct($id,$title,$content)
    {
      $this->id = $id;
      $this->title = $title;
      $this->content = $content;
    }
}


$foo = new Article(1,"xxxx","bbbbb");

$reflect = new ReflectionClass($foo);
$props   = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED);

foreach ($props as $prop) {
    $prop->setAccessible(true);
    print $prop->getName() . "\t";
    print $prop->getValue($foo)."\n";
}

如果不使用setAccessible则会报错

PHP Fatal error: Uncaught ReflectionException: Cannot access non-public member

具体使用场景

想 json 序列化输出对象,但是对象的成员都是私有变量,json_encode 是空的,所以想到下面的方式。

class Article
{
    private $id;
    private $user;
    private $title;
    public $content;

    function __construct($id, User $user, $title, $content)
    {
        $this->id = $id;
        $this->user = $user;
        $this->title = $title;
        $this->content = $content;
    }
}

class User
{
    private $id;
    private $username;

    public function __construct($id, $username)
    {
        $this->id = $id;
        $this->username = $username;
    }
}

function obj_to_array_demo($obj)
{
    $reflect = new ReflectionClass($obj);
    $props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED);

    $array = [];
    foreach ($props as $prop) {
        $prop->setAccessible(true);
        $key = $prop->getName();
        $value = $prop->getValue($obj);
        if (is_object($value)) {
            $value = obj_to_array_demo($value);
        }

        $array[$key] = $value;
    }

    return $array;
}

$user = new User(1, "周梦康");
$foo = new Article(1, $user, "xxxx", "bbbbb");
var_export(obj_to_array_demo($foo));

输出结果

array (
  'id' => 1,
  'user' =>
  array (
    'id' => 1,
    'username' => '周梦康',
  ),
  'title' => 'xxxx',
  'content' => 'bbbbb',
)

封装到工具库里

/**
 * 针对成员都是私有属性的对象
 * @param $obj
 * @param bool $removeNull 去掉空值
 *
 * @return array
 */
public static function Obj2Array($obj, $removeNull=true)
{
    $reflect = new \ReflectionClass($obj);
    $props = $reflect->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED);

    $array = [];
    foreach ($props as $prop) {
        $prop->setAccessible(true);
        $key = $prop->getName();
        $value = $prop->getValue($obj);

        if ($removeNull == true && $value === null) {
            continue;
        }

        if (is_object($value)) {
            $value = self::Obj2Array($value);
        }

        $array[$key] = $value;
    }

    return $array;
}

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表