php的动态代理和反射

面向对象的高级语言都应该提供了反射机制,可以动态的获取类的信息,否则语言就缺少灵活性,很多需求无法完成,php的反射相当于iOS里面的运行时方法。iOS的运行系统提供了一系列的C语言方法动态的获取类的信息,处理消息转发,php也提供了类似的实现,相比iOS使用更简便,下面是几个案例。

  1. 获取函数的信息
<?php
/**
 * Created by PhpStorm.
 * User: wangguodong
 * Date: 17/3/2
 * Time: 下午10:44
 */

/**
 * 这是testfun的注释
 */
function testfun($name = 'test'){
    echo "this is a $name method";
    return 'a';
}

testfun();
//通过一个函数名初始化一个函数反射对象,取获取函数的相关信息
$ref_fun = new ReflectionFunction('testfun');
//函数的所在的文件
echo '<br>函数的文件位置是:'.$ref_fun->getFileName();
//获取函数的开始行编号
echo '<br>函数的起始位置是:'.$ref_fun->getStartLine();
//获取函数末尾的编号
echo '<br>函数的结束位置是:'.$ref_fun->getEndLine();
//函数的注释
echo '<br>函数的注释是:'.$ref_fun->getDocComment();
//获取参数的个数
echo '<br>函数的参数个数是:'.$ref_fun->getNumberOfParameters();
//获取具体的参数信息
echo '<br>函数的参数是:';print_r($ref_fun->getParameters());
//函数的返回值 --这里提示这个方法不存在
echo '<br>函数的返回值是:'.$ref_fun->getReturnType();

//如果反射一个不存在的函数,会抛出一个异常,应该try catch 使用
try{
    $ref_nfun = new ReflectionFunction('no_exist');
}catch (ReflectionException $e){
    echo $e->getMessage();
}

2.类的信息

class Person{

    public $name,$age,$sex;
    static function show($name,$age,$sex='男'){
        echo "姓名:$name,年龄:$age,性别:$sex";
    }
    function say($content){
        echo "我想说的是:$content";
    }
    function eat($food= 'apple'){

    }
}
$per = new Person();

$ref = new ReflectionClass('Person');//参数可以是类名,或者类的实例
//获取类里面的所有方法
$class_methods = $ref->getMethods();
//是一个数组,每个对象包含了方法名和所属类
echo '<br/>';
echo "<pre>";print_r($class_methods);echo "<pre>";
//是否拥有某个方法
$has_method = $ref->hasMethod('say');
//获取某个方法的信息
$some_method = new ReflectionMethod('Person','say');
$some_method->isPrivate();//判断是否私有,还有static,public
//方法的调用,
if ($some_method->isPublic()&&!$some_method->isAbstract()) {

    if ($some_method->isStatic()){
        //静态方法第一个参数是null,后面参数写方法的参数,可以传递一个或者多个,并且这个方法可以接受数量可变的参数。
        /*
         * * The object to invoke the method on. For static methods, pass
         * null to this parameter.
         * </p>
         * @param mixed $parameter [optional] <p>
         * Zero or more parameters to be passed to the method.
         * It accepts a variable number of parameters which are passed to the method.
         * </p>
         */
        $some_method->invoke(null,'zhangsan','23');
    }
    else {
        //非静态方法第一个参数传递一个对象
        $some_method->invoke($per,'生活真好');
    }
}
}
  1. 动态代理

消息的转发,交给其他类处理,iOS可以通过delegate实现,也可以在运行时通过相应的方法转发。

//调用B的show方法时候去调用A的show方法
class A{
    function show(){
        echo "classA的show方法";
    }
}
class B{
    private $obj;
    function __construct(){
        $this->obj = new A();
    }
    function __call($name, $arguments)
    {
         $ref = new ReflectionClass($this->obj);
         if ($ref->hasMethod($name)){
             $method = $ref->getMethod($name);
             if ($method->isPublic()&&!$method->isAbstract()&&count($arguments)){
                 if ($method->isStatic()){
                     $method->invoke(null);
                 }
                 else{
                     $method->invoke($this->obj);
                 }
             }
         }
    }
}
  1. 插件案例
include_once __DIR__."/plugin.php";
function get_plugin_menus(){
    $menus = array();
    $all_class = get_declared_classes();//获取所有的类
    foreach ($all_class as $cls){
        $ref_cls = new ReflectionClass($cls);
        if ($ref_cls->implementsInterface('Plugin')){//是否实现了某个接口
            if ($ref_cls->hasMethod('showMenu')){
                $method = $ref_cls->getMethod("showMenu");
                if ($method->isStatic()){
                    $method->invoke(null);
                }
                else{
//                    $method->invoke(new $cls());//这样获取类
                    $instance = $ref_cls->newInstance();
                    $menu = $method->invoke($instance);
                }
            }
        }
        $menus = array_merge($menus,$menu);
    }
    return $menus;
}
echo "<pre>";get_plugin_menus();echo "<pre>";

interface Plugin{
    function showMenu();
}
class MyPlugin implements Plugin{

    function showMenu()
    {
        $menu = array(
            array(
                'name' => 'menu1', 'link' => 'index.php?act=link1'
            ),
            array(
                'name' => 'menu2', 'link' => 'index.php?act=link2'
            )
        );
        return $menu;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,796评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 曾几何时,手机走进人们的生活,改变着传统的联系方式,原来当面可以说的事情现在可以通过手机和短信留言来完成,曾...
    伟嘉豪阅读 203评论 0 1
  • 这个中秋节,老王本打算静下来写写文章,但在无意间看到一部《麻雀》的谍战片,使得老王两眼冒金光,因为老王超喜欢...
    楚先生阅读 348评论 0 1
  • 致孤单的你 每个人都会有孤单寂寞的时候,并不是有人陪伴就不会孤单寂寞,孤单的时候学会独处,看一本书,听一首歌,写一...
    猴爸陪你读书阅读 328评论 0 1