筋斗云接口编程 / 创建Web接口项目

[任务]

用筋斗云框架创建一个Web接口项目叫mysvc,创建数据库,提供对ApiLog对象的操作接口。

先从github上下载开源的筋斗云后端框架及示例应用:https://github.com/skyshore2001/jdcloud-php

建议安装git工具直接下载,便于以后更新,例如直接创建Web接口项目叫mysvc:

git clone https://github.com/skyshore2001/jdcloud-php.git mysvc

如果github访问困难,也可以用这个git仓库: http://dacatec.com/git/jdcloud-php.git

配置好Web服务器,php环境和MySQL数据库。
注意PHP最低版本需要5.4版本,需要打开mysql, pdo, gd等支持。

在Web服务器上将项目下的接口主目录(即server目录)暴露出来,假设URL是:

http://localhost/mysvc/

先别急着访问这个地址,而是先配置数据库连接等,在浏览器中打开这个页面:

http://localhost/mysvc/tool/init.php

这个工具会先检查运行环境是否正确,如有异常(比如php版本不对,缺少组件等)请先解决。
然后创建接口应用使用的数据库和配置文件。

初始化工具运行完后,生成的配置文件为php/conf.user.php,之后也可以手工编辑该文件。

数据模型定义在主设计文档DESIGN.wiki中,作为示例,里面定义了一些数据模型,像用户(User),订单(Ordr)以及前面提过的操作日志(ApiLog)等,还定义了一些常用接口,如登录操作(login)等。
我们通过通过命令行工具tool/upgrade.php可以创建或更新数据库:

cd tool
php upgrade.php
(这时进入upgrade交互操作,输入initdb命令创建或更新数据库)
> initdb
(输入命令q退出)
> q

我们进入server目录看看:

  • api.php就是接口应用程序,提供Web接口。
  • tool目录中是一些线上工具,比如查看日志、计划任务等。
  • 对象型接口一般写在文件php/api_objects.php中,函数型接口一般写在php/api_functions.php中。
    里面已经包含了一些示例接口,一般在示例基础上修改即可。
  • 共用逻辑写在app.php中,各种工具和接口应用程序均可用;注意如果只是多个接口共用的逻辑,直接写在api.php文件中就可以。

为了学习对象型接口,我们将php/api_objects.php清空,从头开始来写,以暴露ApiLog对象为例,在php/api_objects.php中加上一句:

class AC_ApiLog extends AccessControl
{
}

这一句代码就提供了对ApiLog对象的标准增删改查(CRUD)接口如下:

查询对象列表,支持分页、查询条件、统计等:
ApiLog.query() -> table(id, tm, addr)

添加对象,通过POST参数传递字段值,返回新对象的id
ApiLog.add()(tm, addr) -> id

获取对象
ApiLog.get(id) -> {id, tm, addr}

更新对象,通过POST参数传递字段值。
ApiLog.set(id)(tm?, addr?)

删除对象
ApiLog.del(id)

[接口原型的描述方式]

在上面的接口原型描述中,用了两个括号的比如add/set操作,表示第一个括号中的参数通过GET参数(也叫URL参数)传递,第二个括号中的参数用POST参数(也叫FORM参数)传递。
多数接口参数支持用GET方式或POST方式传递,除非在接口说明中特别指定。
带”?”表示参数或返回的属性是可选项,可以不存在。

接口原型中只描述调用成功时返回数据的数据结构,完整的返回格式是[0, 返回数据];而在调用失败时,统一返回[非0错误码, 错误信息]

我们可以直接用curl工具来模拟前端调用,用add接口添加一行数据,使用HTTP POST请求:

curl http://localhost/mysvc/api.php/ApiLog.add -d "tm=2016-9-9 10:10" -d "addr=shanghai"

curl用”-d”参数指定参数通过HTTP body来传递,由于默认使用HTTP POST谓词和form格式(Content-Type=application/x-www-form-urlencoded),
这种参数一般称为POST参数或FORM参数,与通过URL传递的GET参数相区别。
结果输出一个JSON数组:

[0,11338]

0表示调用成功,后面是成功时返回的数据,add操作返回对象id,可供get/set/del操作使用。

用get接口取出这个对象出来看看:

curl http://localhost/mysvc/api.php/ApiLog.get?id=11338

输出:

[0,{"id":11338,"tm":"2016-09-09 00:00:00","addr":"shanghai"}]

这里参数id是通过URL传递的。
前面说过,未显式说明时,接口的参数可以通过URL或POST参数方式来传递,所以本例中URL参数id也可以通过POST参数来传递:

curl http://localhost/mysvc/api.php/ApiLog.get -d "id=11338"

如果取一个不存在的对象,会得到错误码和错误信息,比如:

curl http://localhost/mysvc/api.php/ApiLog.get?id=999999

输出:

[1,"参数不正确"]

再用set接口做一个更新,按接口要求,要将id参数放在URL中,要更新的字段及值用POST参数:

curl http://localhost/mysvc/api.php/ApiLog.set?id=11338 -d "addr=beijing"

输出:

[0, "OK"]

再看很灵活的query接口,取下列表,默认支持分页,会输出一个nextkey字段:

curl http://localhost/mysvc/api.php/ApiLog.query

返回示例:

[0,{
    "h":["id","tm","addr"],
    "d":[[11353,"2016-01-04 18:31:06","::1"],[11352,"2016-02-04 18:30:43","::1"],...],
    "nextkey":11349
}]

返回的格式称为压缩表,”h”为表头字段,”d”为表的数据,在接口描述中用table(id, 其它字段...)表示。

默认返回的JSON数据未经美化,效率较高,如果想看的清楚些,可以在配置文件conf.user.php中设置测试模式:

putenv("P_TEST_MODE=1");

测试模式不仅美化输出数据,还可返回更多调试信息,前端可用URL参数_debug设置调试等级0-9,如果设置为9,甚至可以查看SQL调用日志:

curl http://localhost/mysvc/api.php/ApiLog.query?_debug=9

这在调试SQL语句时很有用。此外,测试模式还会开放某些内部接口,以及缺省允许跨域访问,便于通过web页面测试接口。注意线上生产环境绝不可设置为测试模式。

query接口也支持常用的数组返回,需要加上_fmt=list参数:

curl http://localhost/mysvc/api.php/ApiLog.query -d "_fmt=list"

返回示例:

[0,{
    "list": [
        { "id": 11353, "tm": "2016-01-04 18:31:06", "addr": "::1" },
        { "id": 11352, "tm": "2016-02-04 18:30:43", "addr": "::1" }, 
        ...
    ],
    "nextkey":11349
}]

还可以将_fmt参数指定为”csv”, “excel”, “txt”等,在浏览器访问时可直接下载相应格式的文件,读者可自己尝试。

取下一页可以用_pagekey字段,还可指定一次取的数据条数,用_pagesz字段:

curl "http://localhost/mysvc/api.php/ApiLog.query?_pagekey=11349&_pagesz=5"

不仅支持分页,query接口非常灵活,可以指定返回字段、查询条件、排序方式,
比如查询2016年1月份的数据(cond参数),结果只需返回id, addr字段(res参数,也可用于get接口),按id倒序排列(orderby参数):

curl http://localhost/mysvc/api.php/ApiLog.query -d "res=id,addr" -d "cond=tm>='2016-1-1' and tm<'2016-2-1'" -d "orderby=id desc"

甚至可以做统计,比如查看2016年1月里,列出访问次数排名前10的地址,以及每个地址访问了多少次服务器,也可以通过query接口直接查出。
做一个按addr字段的分组统计(gres参数):

curl http://localhost/mysvc/api.php/ApiLog.query -d "gres=addr" -d "res=count(*) cnt" -d "cond=tm>='2016-1-1' and tm<'2016-2-1'" -d "orderby=cnt desc" -d "_pagesz=10"

输出示例:

[0,{
    "h":["addr","cnt"],
    "d":[["140.206.255.50",1],["101.44.63.119",73],["121.42.0.85",70],...],
    "nextkey": 3
}]

[接口调用的描述方式]

在之后的示例中,我们将使用接口原型来描述一个调用,不再使用curl,比如上面的调用将表示成:

ApiLog.query(gres=addr
    res="count(*) cnt"
    cond="tm>'2016-1-1' and tm<'2016-2-1'"
    orderby="cnt desc"
    _pagesz=10
)
->
{
    "h":["addr","cnt"],
    "d":[["140.206.255.50",1],["101.44.63.119",73],["121.42.0.85",70],...],
    "nextkey": 3
}

返回数据如非特别声明,我们将只讨论调用成功时返回的部分,比如说返回”OK”实际上表示返回[0, "OK"]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章