php在框架内封装反射类实现anotation

概要:

在学习Java的过程中必定绕不开的是Java的注解,似乎处处都使用到这个看起来不是代码的代码,对于初级PHPer来说就觉得莫名其妙了,我在用php开发的时候就觉得php怎么没有Java这么多的弯弯绕绕呢?其实也是自己原本实力就有限,许许多多的php框架都必不可少的使用到了这种机制,只是没有暴露在我们使用者的眼前而已。

简介:关于php的反射

PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。

在开发中用到的场景

在开发过程中,除了使用swagger这样自动生成文档之外,还可以在将业务的一些前置校验抽离到注释当中,使用反射来获取类、方法的信息进行校验。
我们可以在controller的业务方法上面进行如下注释:

namespace app\admin\controller;
use app\admin\service\Admin as AdminService;
use app\lib\Response;
class Admin extends BaseController
{
    /**
     * @Api(后台登录接口,1,POST)
     */
    public function login($username,$password) {
        $adminData = AdminService::adminLogin($username,$password);
        return new Response(['data'=>$adminData]);
    }
}

上述代码中为控制器的login方法中,通过@Api(后台登录接口,1,POST)这样来注释方法的一些参数,例如最后的post可以自定义为该方法需要用post才能访问,然后书写下方的获取该注释的类,并在框架进入控制器目标方法之前进行校验。

use app\admin\model\Api;
use app\lib\exception\DevException;
use ReflectionMethod;
use think\Cache;

/**
 * 通过反射获取api对应函数信息
 * Class ActionInfo
 * @package app\lib
 */
class ActionInfo
{

    protected static $ref = null;
    public static $path = null;
    public static $params = null;
    public static $desc = null;
    public static $type = null;
    public static $method = null;

    private function __construct()
    {
    }

    public static function init($class,$action,$path) {
        if(!self::$ref) {
            self::$ref = new ReflectionMethod($class, $action);
            self::$params = json_encode(self::$ref->getParameters());
        }
        if(!self::$path) {
            self::$path = $path;
        }
        self::getApi('@Api')//获取反射类注释的@Api字样的信息
    }


    protected static function getApi($tag) {
        $str = self::getDocComment(self::$ref->getDocComment(), $tag);
        if(empty($str)) {
            return;
        }
        $infos = explode(',',$str);
        try{
            self::$desc = $infos[0];
            self::$type = $infos[1];
            self::$method = $infos[2];
        } catch (\Exception $e) {
            throw new DevException(['msg'=>'控制器方法@api注释错误']);
        }
    }

    protected static function getDocComment($str, $tag = '')
    {
        if (empty($tag)) {
            return $str;
        }
        $matches = array();
        preg_match("/".$tag."\\((.*)(\\r\\n|\\r|\\n|\\))/U", $str, $matches);
        if (isset($matches[1])) {
            return trim($matches[1]);
        }
        return '';
    }
}

如上获取到了类方法的注释信息,这样我们可以配置选项就多了,只需要修改上面的获取信息类,甚至可以如下写来限制我们想要的参数

namespace app\admin\controller;
class Admin extends BaseController
{
    /**
     * @Permission(admin/login)
     * @Method(POST)
     */
    public function login($username,$password) {
    }
}

或者是如下的书写方法:

namespace app\admin\controller;
class Admin extends BaseController
{
    /**
     * @Permission(admin/login,POST)
     */
    public function login($username,$password) {
    }
}

你可能感兴趣的:(php)