您的位置:首页 > 编程语言 > PHP开发

php面向对象视频笔记之第六章(反射机制与动态代理)

2017-01-25 23:48 811 查看
1、反射机制与动态代理
php的Reflection反射机制
 php5添加了一项新的功能:Reflection。这个功能使得程序员可以reflection class,interfacce,function,
method...。通过php代码,就可以得到某类/方法等的所有信息,并且可以和它交互。



 反射机制的应用:

   动态代理:也叫委托模式,在委托模式中,有两个对象参与处理同个请求,接受请求的对象将请求委托给另一

个对象来处理。

   插件系统:利用反射机制自动获取插件列表以及其它的相关信息。

ReflectionFunction应用示例如下即运行结果:

<?php

/**
测试函数注释
*/
function test(){
//code
echo '我是一个测试的函数.<br />';
}

test();

$ref_fun = new ReflectionFunction('test');//参数即函数名

echo $ref_fun->getDocComment();//函数注释
echo '<br />定义在文件:',$ref_fun->getFileName();//函数定义所在的文件
echo '<br />代码开始行:',$ref_fun->getStartLine();//开始行
echo '<br />代码结束行:',$ref_fun->getEndLine();//结束行

try{
new ReflectionFunction('test1');
}catch(ReflectionException $e){
echo '<br />',$e->getMessage();
}


php用反射机制实现动态代理

ref.php

<?php
class A{
function t1(){
echo '我是一个不带参数的方法t1<br />';
}
function t2($str){
echo '我是一个带一个参数的方法t2,参数是:',$str,'<br/ >';
}
private function t3(){

}
static function t4(){
echo '我是一个静态方法<br />';
}
}

$a = new A();

$ref_cls = new ReflectionClass('A');//参数可是类名,也可是类的实例如new ReflectionClass($a);
//获取类中的所有方法
$class_all_methods = $ref_cls->getMethods();
print_r($class_all_methods);
echo '<br />以下是判断类中是否有某个方法的结果.<br />';
//判断类中是否有某个方法 hasMethod 返回布尔值
var_dump($ref_cls->hasMethod('t1'));//bool true
echo '<br />';
var_dump($ref_cls->hasMethod('t')); //bool false
echo '<hr />';
echo '以下是判断类中某个方法权限和调用运行的结果.<br />';
//判断方法的修饰符 public protected private static
//判断方式:is+修饰符 返回的是布尔值
//判断之前要获取类中的方法
$ref_method = $ref_cls->getMethod('t1');//参数是方法名

var_dump($ref_method->isPublic());//是否为公开方法 bool true
echo '<br />';
//执行方法
//静态方法调用 invoke(null,参数);
//普通方法调用 invoke(实例对象,参数);
//私有方法不能被invoke调用。
if($ref_method->isPublic() && !$ref_method->isAbstract()){//是公开且非抽象。
if($ref_method->isStatic()){
$ref_method->invoke(null);
}else{
$ref_method->invoke($a);
}
}
//获取类中的方法的反射类(跟上面的方法作用一样)
$ref_method = new ReflectionMethod('A','t3');//类名+方法名.
var_dump($ref_method->isPublic());//是否为公开方法 bool false
echo '<br />';
$ref_method = new ReflectionMethod('A','t2');
var_dump($ref_method->isStatic());//是否为静态方法 bool true
echo '<br />';
if($ref_method->isPublic() && !$ref_method->isAbstract()){//是公开且非抽象。
if($ref_method->isStatic()){
$ref_method->invoke(null,'yi');
}else{
$ref_method->invoke($a,'yi');
}
}
运行结果:



dynamic.php

<?php
class A{
function showInfoA(){
echo 'function "showInfoA()" of Class A.<br />';
}
}
class C{
function showInfoC(){
echo 'function "showInfoC()" of Class C.<br />';
}
}
class B{
private $obj;

function __construct(){
//$this->obj = new A();//添加单个数组元素
}

function addObj($obj){ //动态添加对象数组
$this->obj[] = $obj; //依次后补数组元素
print_r($this->obj);//查看数组元素
echo '<hr />';
}

function __call($name,$args){
foreach($this->obj as $v){//遍历数组元素
$ref_cls = new ReflectionClass($v);//反射出该对象所在类名
if($ref_cls->hasMethod($name)){//判断该类是否有该方法
$ref_method = $ref_cls->getMethod($name);
if($ref_method->isPublic() && !$ref_method->isAbstract())
{
if($ref_method->isStatic()){
$ref_method->invoke(null);
}else{
$ref_method->invoke($v);
}
}
}
}
/*添加单个对象的情况
$ref_cls = new ReflectionClass($this->obj);
if($ref_cls->hasMethod($name)){
$ref_method = $ref_cls->getMethod($name);
if($ref_method->isPublic() && !$ref_method->isAbstract())
{
if($ref_method->isStatic()){
$ref_method->invoke(null);
}else{
$ref_method->invoke($this->obj);
}
}
}*/
}
}

$b = new B();
$b->addObj(new A());
$b->addObj(new C());
$b->showInfoA();
$b->showInfoC();运行结果:



插件雏形示例:

plugin.php:

<?php

interface Plugin{
function showMenu();
}

class MyPlugin implements Plugin{
//获取插件菜单
function showMenu(){
$menu = array(
array(
'name' => 'My_menu1',
'link' => 'index.php?act=my_link1'
),
array(
'name' => 'My_menu2',
'link' => 'index.php?act=my_link2'
)
);

//print_r($menu);
return $menu;
}
}

class YourPlugin implements Plugin{
//获取插件菜单
function showMenu(){
$menu = array(
array(
'name' => 'Your_menu1',
'link' => 'index.php?act=your_link1'
),
array(
'name' => 'Your_menu2',
'link' => 'index.php?act=your_link2'
)
);

//print_r($menu);
return $menu;
}
}

demo.php:
<?php
//echo __DIR__; 当前目录
include_once __DIR__.'/plugin.php';//在当前目录加上此文件

function get_plugin_menus(){
$all_class = get_declared_classes();
//print_r($all_class);
$menu = $menus = array();
foreach($all_class as $cls){
$ref_cls = new ReflectionClass($cls);
//判断这个类是否实现了某个接口
if($ref_cls->implementsInterface('Plugin')){
//echo $cls,'<br />';
if($ref_cls->hasMethod('showMenu')){
$ref_method = $ref_cls->getMethod('showMenu');
if($ref_method->isPublic() && !$ref_method->isAbstract()){
if($ref_method->isStatic()){
$menu = $ref_method->invoke(null);
}else{
//通过反射类获取类的一个实例
//$menu = $ref_method->invoke(new $cls());
$instance = $ref_cls->newInstance();
$menu = $ref_method->invoke($instance);
}
//合并菜单
$menus = array_merge($menus,$menu);
}
}
}
}
//print_r($menus);
return $menus;
}

$menu_list = get_plugin_menus();
foreach($menu_list as $menu){
echo '<a href="'.$menu['link'].'">'.$menu['name'].'</a><br />';//菜单超链接
}运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: