请注意,继承的属性会返回,但父类的私有属性不会返回。根据用例,您也需要检查这一点。
do {
foreach ($reflectionClass->getProperties() as $property) {
/* ... */
}
} while ($reflectionClass = $reflectionClass->getParentClass());
(PHP 5, PHP 7, PHP 8)
ReflectionClass::getProperties — 获取属性
一个包含 ReflectionProperty 对象的数组。
版本 | 描述 |
---|---|
7.2.0 |
filter 现在可以为空。 |
示例 #1 ReflectionClass::getProperties() 过滤示例
此示例演示了可选 filter
参数的使用,它实质上跳过了私有属性。
<?php
class Foo {
public $foo = 1;
protected $bar = 2;
private $baz = 3;
}
$foo = new Foo();
$reflect = new ReflectionClass($foo);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
foreach ($props as $prop) {
print $prop->getName() . "\n";
}
var_dump($props);
?>
上面的示例将输出类似于
foo bar array(2) { [0]=> object(ReflectionProperty)#3 (2) { ["name"]=> string(3) "foo" ["class"]=> string(3) "Foo" } [1]=> object(ReflectionProperty)#4 (2) { ["name"]=> string(3) "bar" ["class"]=> string(3) "Foo" } }
请注意,继承的属性会返回,但父类的私有属性不会返回。根据用例,您也需要检查这一点。
do {
foreach ($reflectionClass->getProperties() as $property) {
/* ... */
}
} while ($reflectionClass = $reflectionClass->getParentClass());
第一个示例中的代码实际上至少在 php 5.5.9 中获取了继承的属性。我不知道这种行为何时/是否改变。
以下是输出
array(2) {
[0] =>
class ReflectionProperty#2 (2) {
public $name =>
string(2) "a2"
public $class =>
string(2) "AA"
}
[1] =>
class ReflectionProperty#3 (2) {
public $name =>
string(2) "a1"
public $class =>
string(1) "A"
}
}
有些人可能觉得这很有用。
<?php
/**
* 递归函数,用于获取类属性的关联数组,属性名 => ReflectionProperty() 对象
* 包括从扩展类继承的属性
* @param string $className 类名
* @param string $types 任何组合的 <b>public, private, protected, static</b>
* @return array
*/
function getClassProperties($className, $types='public'){
$ref = new ReflectionClass($className);
$props = $ref->getProperties();
$props_arr = array();
foreach($props as $prop){
$f = $prop->getName();
if($prop->isPublic() and (stripos($types, 'public') === FALSE)) continue;
if($prop->isPrivate() and (stripos($types, 'private') === FALSE)) continue;
if($prop->isProtected() and (stripos($types, 'protected') === FALSE)) continue;
if($prop->isStatic() and (stripos($types, 'static') === FALSE)) continue;
$props_arr[$f] = $prop;
}
if($parentClass = $ref->getParentClass()){
$parent_props_arr = getClassProperties($parentClass->getName());//递归
if(count($parent_props_arr) > 0)
$props_arr = array_merge($parent_props_arr, $props_arr);
}
return $props_arr;
}
//用法
class A{
public $a1;
function abc(){
//执行某些操作
}
}
class AA extends A{
public $a2;
function edf(){
//执行某些操作
}
}
class AAA extends AA{
//可能没有额外的属性,但可能具有额外的函数
function ghi(){
//正常
}
}
//$ref = new ReflectionClass('AAA'); $props = $ref->getProperties();//这将获取不到任何属性!
$props_arr = getClassProperties('AAA', 'public');//使用此方法
var_dump($props_arr);
/*
PHP5.2.6 上的输出:
array
'a1' =>
object(ReflectionProperty)[4]
public 'name' => string 'a1' (length=2)
public 'class' => string 'AAA' (length=3)
'a2' =>
object(ReflectionProperty)[3]
public 'name' => string 'a2' (length=2)
public 'class' => string 'AAA' (length=3)
*/
?>
需要注意的是,getProperties(filter) 方法中的“filter”参数应该为 long 类型。原因不明,但它不能作为字符串传递,用于根据字符串匹配获取属性子集。
看起来您可以通过将对象转换为数组来访问公共、受保护和私有变量(对单元测试很有用)。但是,转换为数组仍然不允许您访问受保护和私有的静态变量。
在 PHP 5.3.0+ 中,使用 ReflectionProperty::setAccessable(true);
<?php
echo "PHP 版本: ".phpversion()."\n";
class Foo {
public $foo = 'public';
protected $bar = 'protected';
private $baz = 'private';
public static $sfoo = 'public static';
protected static $sbar = 'protected static';
private static $sbaz = 'private static';
const COO = 'const';
}
$obj = new Foo;
$arr = (array)$obj;
print_r($arr);
echo "访问公共静态变量: ".Foo::$sfoo."\n";
// echo Foo::$sbar."\n"; // 致命错误:无法访问受保护的属性 Foo::$sbar
// echo Foo::$sbaz."\n"; // 致命错误:无法访问私有属性 Foo::$sbaz
echo "访问常量: ".Foo::COO."\n";
?>
PHP 版本: 5.2.12
数组
(
[foo] => public
[*bar] => protected
[Foobaz] => private
)
访问公共静态变量: public static
访问常量: const
PHP 版本: 5.1.6
数组
(
[foo] => public
[*bar] => protected
[Foobaz] => private
)
访问公共静态变量: public static
访问常量: const
在 PHP 5.3 中,使用 setAccessible() 可以轻松访问受保护或私有属性。但是,有时需要这样做(例如,单元测试),下面是一个用于 getValue() 的解决方法。
<?php
$class = new ReflectionClass('SomeClass');
$props = $class->getProperties();
// $propsStatic = $class->getStaticProperties();
$myPrivatePropertyValue = $props['aPrivateProperty'];
?>
请注意,如果您直接使用 getProperty() 访问属性,则此方法将不起作用。