大话PHP反射机制

反射 PHP

可能大家刚听到‘反射’这个名次的时候那,会感觉一头雾水。是不是还有折射什么的;好了下面我就给大家进行一个介绍;

其实PHP 面向对象编程中被赋予了自省的能力,而这个自省的过程就是反射。直观的理解就是根据到达地找出出发点和来源。具体点说那它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。
其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。

1、在使用例子中更好的理解反射

例子1

有一个Person类如下:

class Person {    
    /**  
     * 设置age属性为私有的 
     */   
    private $age = 18;  

    /** 设置性别 */  
    protected $sex = 0;  

    /** 用户姓名 */  
    protected $name;  

    /*  设置用户的昵称 */
    public  $nickname; 

    /*  获取用户的昵称 */
    public function getName()  
    {  
        return $this->name;  
    }  
    /*  设置用户的昵称 */
    public function setName($v)  
    {  
        $this->name = $v;  
    }  
    /*  获取用户的昵称 */
    public function getNickname()  
    {  
        return $this->nickname;  
    }  

}  

那么我们获取这个Person的对象和属性列表该怎么做那,请看下面的代码

$student = new Person();
$student->setName('sqc');
$student->nickname='sqchr';
// 获取对象的属性列表
$reflect = new ReflectionObject($student);
$props = $reflect->getProperties();
foreach($props as $prop){
    print $prop->getName()."\n";
}
// 获取对象方法的列表
$m = $reflect->getMethods();
foreach($m as $prop){
    print $prop->getName()."\n";
}

结果:

age
sex
name
nickname
getName
setName
getNickname

下面这个是使用class函数来达到咱们的需求,非反射api

// 获取对象属性列表和所属的类
echo get_class($student);
// 返回对象的属性的关联数组
var_dump(get_object_vars($student));
// 类属性
var_dump(get_class_vars(get_class($student)));
// 返回由类的方法名组成的数组
var_dump(get_class_methods(get_class($student)));

结果:

Person

array(1) {
  ["nickname"]=>
  string(5) "sqchr"
}

array(1) {
  ["nickname"]=>
  NULL
}

array(3) {
  [0]=>
  string(7) "getName"
  [1]=>
  string(7) "setName"
  [2]=>
  string(11) "getNickname"
}

反射API功能显然更加的强大,甚至能还原这个类的原型,包括方法的访问权限。

// 反射获取类的原型
$obj = new ReflectionClass('Person');
$className = $obj->getName();
$Methods = $Properties = array();

// 获取对象的属性列表
foreach($obj->getProperties() as $v1){
    $Properties[$v1->getName()] = $v1;
}
// 获取对象方法的列表
foreach($obj->getMethods() as $v2){
    $Methods[$v2->getName()] = $v2;
}
is_array($Properties)&&ksort($Properties);

// 还原类
echo "{$className}\n{\n";
foreach($Properties as $k=>$v){
    echo "\t";
    echo $v->isPublic() ?'public':'',$v->isPrivate() ? 'private':'',$v->isProtected() ? 'protected':'',$v->isStatic() ? 'static':'';
    echo "\t{$k}\n";
}
echo "\n";
is_array($Methods)&&ksort($Methods);
foreach($Methods as $k=>$v){
    echo "\t";
    echo "function {$k} (){}\n";
}
echo "}";

结果:

Person
{
    private age
    protected   name
    public  nickname
    protected   sex

    function getName (){}
    function getNickname (){}
    function setName (){}
}

反射类把不应该暴露的属性和方法强制暴露了出来,用好优雅,用不好缺点明显。

反射类不仅可以用于对象和类,还可以用于函数,扩展模块、异常等。

更多信息请查看 http://php.net/manual/zh/book.reflection.php