请注意,继承的属性将被返回,但不会返回父类的私有属性。根据用例的不同,您也需要检查这一点。
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(){
//ok
}
}
//$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)
*/
?>
看起来你可以通过将对象转换为数组来访问公共、受保护和私有变量(对单元测试很有用)。但是,转换为数组仍然无法访问受保护和私有的静态变量。
在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()访问属性,则此方法无效。