Skip to content
caoym edited this page Dec 9, 2015 · 18 revisions

phprs用户手册

定义接口

phprs通过@注释定义类的路由、绑定输入输出、管理依赖

类注释

在类头部的注释中声明

  • @path

    必选

    形式:

    @path("/myapi")
    指定此类下所有接口都在/myapi路径下(这里指url路径, 而不是文件在磁盘上的路径)

方法注释

  • @route

    必选

    声明方法对应的路由

    如果有多个路由匹配, 则命中最严格的规则

    同一个方法可以声明多个@route

    形式:

    @route("GET", "func1")
    匹配 GET /myapi/func1

    @route("*", "func1")
    匹配 所有方法 /myapi/func1

    @route("GET", "func1?param=1")
    匹配GET /myapi/func1?param=1, 其中query_string参数的先后顺序无关(如/myapi/func1?param2=x&param=1也匹配)

    @route("GET", "patha/*")
    匹配GET /myapi/patha/下所有子路径,如/myapi/patha/123, 但不匹配/myapi/patha

    @route("GET", "patha/*\/pathb")
    匹配GET /myapi/patha/下所有子路径中存在pathb的

    @route("GET", "resources/type1")
    @route("GET", "resources/type2")
    @route("GET", "resources/type3")
    

    匹配其中任意一条规则, 就调用接口

  • @param

    必选(如果方法有参数)

    声明方法的参数, 如果被声明的参数不存在, 且此参数没有默认值, 请求调用时,将抛出异常.

    如果参数是引用方式传递, 则参数的来源可以在方法内部修改, 这在实现hook时很有用.

    形式:

    @param({"arg0","$._GET.param0"})
    指定方法被调用时,"$._GET.param0"对应的值将被作为参数$arg0,"$._GET.param0"是jsonpath表达式, 可以搜索$GLOBALS数组中的数据, 除此之外还有一些特殊的变量: $.path 获取当前请求的路径(相对于Router中指定的root_path, 默认是相对于"/" )

    @param({"arg1","123"})
    指定方法被调用时,字符串常量"123"将被作为参数$arg1

  • @return

    可选

    声明方法的返回

    如果不声明@return, 将把方法的返回值作为http的body输出,输出时,数组将被json_encode成字符串

    输出可以支持变量($开头)和常量(不以$开头)

    形式:

    @return({"output_func", "$arg1","$arg2"...})
    将通过output_func输出,output_func的两个参数分别是方法的参数$arg1,$arg2.$arg1,$arg2必须是引用参数

    @return({"body"})
    输出body, 将方法的返回值作为http的body输出

    @return({"body", "$arg0"})
    输出body, 取方法的$arg0参数(必须是引用参数)作为http的body输出

    @return({"cookie", "$name", "$value", "$expire" })
    输出cookie, 参数形式参考 setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )

    @return({"header", "$name", "$value", "$expire" })
    输出header,参数形式参考void header ( string $string [, bool $replace = true [, int $http_response_code ]] )

    @return({"status", "200 OK" })
    输出http status code

    @return({"res", "200 OK", {"res":"ok"} })
    输出http status code + body

  • @throws

    声明方法的异常, 声明后的, 方法如果抛出异常, 将被捕获

    不要去尝试捕获所有异常, 原则上内部错误的异常都不要捕获, 只有如验证失败, 参数错误等外部异常, 需要根据异常指定不同的http status, 如"400 Bad Request"

    形式:

    @throws({"MyException","output_fun", "arg0", "arg1"})
    如果捕获MyException异常, 则通过output_fun输出,output_fun的参数是arg0, arg1. 支持的输出方式与@return一致. 匹配异常的规则是,如果有完全匹配的异常(异常类一样), 则只执行完全匹配的异常, 否则匹配异常的父类

    @throws({"NotFoundException", "status", "404 Not Found"})
    如果匹配异常NotFoundException, 则status输出404 Not Found

  • @cache

    可选

    声明方法的结果是否缓存, 下次收到同样的输入参数时, 不执行此方法, 而是直接返回

    形式:

    @cache({"ttl", 3600}))
    使用缓存, 且缓存的有效期是3600秒

    @cache({"check", "$check"}))
    使用缓存, $check是方法的变量(通过引用返回),缓存的过期通过调用$check($data, $create_time)判断, 返回false表示过期, 如$check = newFileExpiredChecker('file.tmp'); 通过判断file.tmp是否修改, 判断缓存是否过期.

    框架默认使用apc缓存,可以通过配置文件指定其他缓存方式如:

    {
    ...
    
    "tinyESB\\rsapi\\Invoker": {
        "properties": {
            "cache":"invokeCache"// 1.指定接口调用使用的缓存实例
        } 
    },
     //缓存实例的配置
    "invokeCache":{
        "class":"utils\\RedisCache",
        "singleton":true,
        "properties":{
            "serialize":true,
            "host":"127.0.0.1",
            "port":"6379"
        }
    },
    
    ...
    }

属性注释

在方法的属性中声明的注释

  • @property

    可选

    注入属性, 在创建类时(构造函数调用之前), 由IoCFactory从配置文件中读取, 注入实例.

    属性会在__construct之前被注入,所以可以在__construct中访问被注入的属性。 形式:

    /** @property */
    private $name;

    $name是一个属性, 且是必须被注入的

    /** @property */
    private $name='value';

    $name是一个属性, 可选, 有默认值

    /** @property({"optional":true}) */
    private $name;

    $name是一个属性, 可选, 没有默认值

  • @inject

    可选

    注入外部依赖

    形式:

    /** @inject("$.path[0]") */
    private $app_name;
    
    /** @inject("$.factory") 注入创建该实例的工厂实例*/
    private $factory; 

    与方法的参数注入类似, 但不同的是, 属性会在类实例化的时候就注入

配置接口

  • 典型的配置文件
    {
        "key": 
        {
            "class":"class_name", //可选, 指定真正的类名,如果不指定, 则使用key作为类名
            "singleton":true,// 可选,是否是单例, 默认是false
            "pass_by_construct":true,//可选, 属性是否以构造方法参数的形式传递, 默认是false
            "properties": 
            { //注入的属性
                 "name1": "{tpl}/apis/", //{tpl}模板变量,加载配置文件时被替换
                 "name2": "value",
                 "name3":"@key1" //@表示引用, 即取key1的实例作为值
            }
        },
        "key1":{
            ...
        }
  • 示例
    {
        "caoym\\phprs\\RouterWithCache": 
        { //下面是针对RouterWithCache的配置
            "properties": 
            {
                "api_path": "{app_root}/apis/", //扫描api类的目录
                "cache":"@caoym\\util\\Cache" //缓存的实现类
            }
        },
        "caoym\\phprs\\Router": 
        { // 针对Router的配置
            "properties": 
            {
                "hooks": ["Hook1","Hook2"] //指定hook执行顺序
            }
        },
        //接口类配置
        "MyApi1":
        {
            "properties": 
            {
                "conf1": "conf value 1",
                "conf2": "conf value 2"
            }
        }
    }

hook实现

hook实现与接口实现完全一致, 不同的是hook要放在api目录下的hooks中, 同时在配置文件中指定caoym\phprs\Router的hooks

hook会在api被调用前, 按配置的顺序执行, 只有匹配路由规则的hook会被执行.

hook中即可以修改请求, 也可以修改响应.

如果要中途结束hook的执行链路(不再执行后续hook和api), 可以指定 @return({"break", 1}) 或者 @return({"break", $is_break})

  • 示例

    /**
     * @path("/hw")
     * @author caoym
     */
    class HookApiName
    {
         /**
         * uri中提取app名,并把app从uri中去掉
         * @route({"GET","/"})
         * @param({"app", "$.app_name"})
         * @param({"ori_path", "$.path"})
         * @param({"dest_path", "$._SERVER.REQUEST_URI"})
         */
         function fetchAppName($ori_path, &$dest_path, &$app){
             $app = $ori_path[0];
             array_shift($ori_path);
             $dest_path = '/hw/'.implode('/', $ori_path);
         }
    }

自动文档

此功能默认关闭, 开启后将允许通过接口("http://your-domain.com/apis/")获取接口本身的文档,形式如下:

<?php
/**
 * doc class
 * @path("doc_sample")
 */
class DocSample
{
 /**
 * doc func
 * @route({"POST", "path1"}) doc path1
 * @route({"POST", "path2"})
 * doc path2
 * @param({"arg0", "$._GET.arg0"}) doc arg0
 * @param({"arg1", "$._POST.arg1"}) doc arg1
 * @return({"body"}) doc return body
 * @return({"status", "200 OK"}) doc return status
 * @return({"header", "$header0"}) doc return $header0
 * @return({"cookie", "token", "$cookie0"}) doc return $cookie0
 * @throws({"Exception", "status", "500 Internal Server Error"}) doc Exception
 */
 public function func($arg0, $arg1, &$header0, &$cookie0){

 }
 /**
 * @inject("$.path[2]")
 * doc common
 */
 private $common;
}

生成的文档如下:

开启方式为设置" caoym\phprs\Router"的属性"export_apis"为true 目前支持文档化的注释有:

@route
@path
@return: status,header,cookie, body,res
@throws:status,header,cookie, body
@param: $.path[?], $._SERVER.HTTP_X_???, $._GET.?, $._POST.?
Clone this wiki locally