php使用反射API

反射是一种对象编程中赋予对象的一种自省能力。通过反射api,我们可以可以找到对象所属类的属性、方法以及它们的访问权限,他是一种动态获取信息以及动态调用对象方法的功能。

在这里,我们假设已经定义了一个person类,而student是这个类的实例化对象,现在要获取这个student对象的方法和属性列表。

(1)通过反射

//获取对象属性列表
$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";
}

(2)使用class函数,返回对象属性的关联数组以及更多的信息

//返回对象属性的关联数组
var_dump(get_object_vars($student));
//类属性
var_dump(get_class_vars(get_class($student)));
//返回由类组成的方法数组
var_dump(get_class_methods(get_class($student)));
*get_class()方法可以知道页面传递对象的所属类。

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

//反射获取类的原型
$obj = new ReflectionObject($student);
$className = $obj->getName();
$methods = $properties = array();
foreach ($obj->getProperties() as $v) {
      $properties[$v->getName()] = $v;
}
foreach ($obj->getMethods() as $v) {
      $methods[$v->getName()] = $v;
}
echo "class {$classname}\n{\n";
is_array($properties)&&ksort($properties);

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";
if(is_array($methods)) ksort($methods);
foreach ($methods as $k => $v) {
      echo "\tfunction{$k}(){}\n";
}

echo "\n";

反射的作用:使用反射原理实现动态代理

class Mysql
{
      public function connect($db)
      {
            echo "连接到数据库${db[0]}\r\n";
      }
}

class SqlProxy
{
      private $target;
      function __construct ($tar) {
            $this->target = new $tar();
      }

      function __call ($name,$args) {
            foreach ($this->target as $obj) {
                  $r = new ReflectionObject($obj);
                  if($method = $r->getMethod($name)) {
                        if($method->isPublic()&&!$method->isAbstract()) {
                              echo "方法前拦截记录LOG\r\n";
                              $method->invoke($obj,$args);
                              echo "方法后拦截\r\n";
                        }
                  }
            }
      }
}
$obj = new SqlProxy('Mysql');
$obj->connect('member');

在上面的代码中,真正的操作类是mysql类,但是sqlporxy类实现了根据动态传入参数,代替实际的类运行,并且在方法运行前后进行拦截,并且动态的改变类中的属性和方法,这就是简单的动态代理。

很多时候,善用反射能够实现代码的优雅和简洁,但是反射会破坏类的封装性,因为反射使本不应该暴露的属性或方法被强制暴露,因此,它在实际开发中不常用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值