您的位置 首页 php

RestFul接口设计,手把手带你学会

一、接口编程

随着互联网的发展,尤其是移动互联网为代表的Web3.0时代,客户端层出不穷,以APP、微信、PC浏览器为代表,服务端业务逻辑基本一致的,那么有没有一种方式可以做到“服务端一次编写,客户端随时接入”呢

流行的方案就是“接口编程”

2、接口编程

API(Application Programming Interface,应用程序编程接口),程序之间交互数据的一种方式。

以浏览器和服务器之间的数据交互(ajax请求)为例:

请求方式:get方式 post方式

请求协议:http协议 https协议

返回参数:普通字符串、json格式、xml格式,现在通用的是json格式。

二、RESTFul设计风格

1、Rest与RestFul

REST(英文:Representational State Transfer,简称REST),表述性状态转移,指的是一组架构原则。

Restful:遵守了rest原则的web服务或web应用。

2、API设计六要素

资源路径(URI)、HTTP动词(Mrthod)、过滤信息(query-string)、状态码(Status-code)、错误信息(Error)、返回结果(Result)

1、资源路径URI

资源:所有在服务器保存的数据(如:音乐/视频/文章/个人信息。。。)都是服务器资源。

URI(Uniform Resource Identifier)/统一资源标志符,包括URL和URN。

URL(Uniform Resource Locator):统一资源定位符。

URN(Uniform Resource Name):统一资源命名

在HTTP协议中,URI的组成如下

Schema://host[:port]/path[?query-string]

Schema:使用的协议类型,如http/https/ftp等

host:主机域名或IP

port:端口号(可选)

path:路径

query-string:查询参数(可选)

2、HTTP动词(请求方式)

对于资源,一般有四个操作,CURD(增、删、改、查)

GET:从服务器获取资源(一项或多项)

POST:在服务器新建一个资源

PUT:在服务器更新资源,服务器返回完整的属性

DELETE:从服务器删除资源

3、过滤信息

通常也叫做请求参数或查询字符串

4、响应状态码

服务端返回的信息,用来告诉客户端操作结果

常见状态码:

状态码

含义

说明

200

OK

操作成功,并返回数据

201

CREATED

新建成功

204

No CONTENT

删除成功

400

BAD REQUEST

请求语法错误

403

Forbidden

请求没有权限的资源

404

NOT FOUND

没有找到请求的资源

GET

200(ok)-表示已在响应中发出

204(无内容)-资源有空表示

301(Moved Permanently)-资源的URI已被更新

303 (See Other)-其他(如,负载均衡)

304 (not Modified)-资源未更改(缓存)

400 (bad request)-指代坏请求(如,参数错误)

404 (not found)-资源不存在

406(not acceptable)-服务端不支持所需展示

500 (internal server error) -通用错误响应

503 (Service Unavaifable) -服务端当前无法处理请求

POST

200(ok)-如果现有资源已被更改

201(created)-如果新资源被创建

202 ( accepted)-已接受处理请求但尚未完成(异步处理)

301(Moved Permanently)-资源的URI被更新

303 (See Other)-其他(如,负载均衡)

400 (bad request)-指代坏请求(如,参数错误)

404 (not found)-资源不存在

406(not acceptable)-服务端不支持所需展示

409(conflict)-通用冲突

412 (Precondition Failed)-前置条件失败(如执行条件更新时的冲突)

415(unsupported media type)-接收到的表示不受支持

500 (internal server error) -通用错误响应

503 (Service Unavaifable) -服务端当前无法处理请求

PUT

200(ok)-如果现有资源已被更改

201(created)-如果新资源被创建

301(Moved Permanently)-资源的URI被更新

303 (See Other)-其他(如,负载均衡)

400 (bad request)-指代坏请求(如,参数错误)

404 (not found)-资源不存在

406(not acceptable)-服务端不支持所需展示

409(conflict)-通用冲突

412 (Precondition Failed)-前置条件失败(如执行条件更新时的冲突)

415(unsupported media type)-接收到的表示不受支持

500 (internal server error) -通用错误响应

503 (Service Unavaifable) -服务端当前无法处理请求

DELETE

200(ok)-资源已被删除

301(Moved Permanently)-资源的URI被更新

303 (See Other)-其他(如,负载均衡)

400 (bad request)-指代坏请求(如,参数错误)

404 (not found)-资源不存在

409(conflict)-通用冲突

500 (internal server error) -通用错误响应

503 (Service Unavaifable) -服务端当前无法处理请求

5、错误信息

如果状态码是4xx或者5xx,需要告诉客户端对应的错误信息,通常以json格式返回:{“error”:“错误信息”;}

6、返回结果

针对不同的操作,服务端需要返回的结果应该符合这样的规范

GET/collections–返回资源列表(数组)

GET/collections/:id –返回单个资源 eg./collections/1

POST/collections –返回新的资源

PUT/collections/:id –返回资源的完整属性

DELETE/collections/:id –返回204状态码+空文档

3、RestFul接口设计风格

RESTFul是一种软件设计风格,主要用于有客户端与服务端交互的软件

RESTFul是目前最流行的API设计规范,用于web数据接口的设计

RESTFul风格的数据接口示例:

以新闻资源为例:URI及HTTP动词设计如下

HTTP动词

URI路径

说明

GET

http://域名/news

获取列表数据

GET

http://域名/news/:id

根据id获取一条数据

POST

http://域名/news

添加一条数据

PUT

http://域名/news/:id

根据id修改一条数据

DELETE

http://域名/news/:id

根据id删除一条数据

三、RestFul实战

1、TP框架中的资源路由

手册-路由-资源路由 手册-控制器-资源控制器

1、创建api模块

 php think build --module api  

2、创建news控制器

 php think make:controller api/News  

3、设置路由(application/route.php)’

 \think\Route::resource('news','api/news');  

相当于设置了以下路由

 \think\Route::get('news','api/news/index');
\think\Route::get('news/create','api/news/create');
\think\Route::post('news','api/news/save');
\think\Route::get('news/:id','api/news/read');
\think\Route::get('news/:id/edit','api/news/edit');
\think\Route::put('news/:id','api/news/update');
\think\Route::delete('news/:id','api/news/delete');  

设置后会自动注册7个路由规则,如下:

标识

请求类型

生成路由规则

对应操作方法(默认)

index

GET

news

index

create

GET

news/create

create

save

POST

news

save

read

GET

news /:id

read

edit

GET

news/:id/edit

edit

update

PUT

news/:id

update

delete

DELETE

news/:id

delete

4、修改News控制器,返回json格式数据

 <?php

namespace app\api\controller;

use think\Controller;
use think\Request;

class News extends Controller
{
 
    /**
     * 显示资源列表
     *
     * @return \think\Response
     */
    public function index()
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'index'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }

    /**
     * 显示创建资源表单页.
     *
     * @return \think\Response
     */
    public function create()
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'create'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }

    /**
     * 保存新建的资源
     *
     * @param  \think\Request  $request
     * @return \think\Response
     */
    public function save(Request $request)
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'save'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }

    /**
     * 显示指定的资源
     *
     * @param  int  $id
     * @return \think\Response
     */
    public function read($id)
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'read'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }

    /**
     * 显示编辑资源表单页.
     *
     * @param  int  $id
     * @return \think\Response
     */
    public function edit($id)
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'edit'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }

    /**
     * 保存更新的资源
     *
     * @param  \think\Request  $request
     * @param  int  $id
     * @return \think\Response
     */
    public function update(Request $request, $id)
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'update'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }

    /**
     * 删除指定资源
     *
     * @param  int  $id
     * @return \think\Response
     */
    public function delete($id)
    {
 
        //返回数据数组
        $res=['code'=>200,'msg'=>'success','data'=>'delete'];
        //返回json格式数据
        //echo json_encode($res);die;//原生php写法
        return json($res);//TP框架的写法
    }
}  

通过postman分别访问以下七个地址:

 请求方式   请求地址
get  			   
get              
post            
get              
get              
put              
delete           

2、ajax请求restful接口

public目录下,创建测试文件api.html

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajax请求restful接口</title>
    <script src="/static/admin/js/jquery-1.8.1.min.js"></script>
</head>
<body>
<input type="button" id="index" value="index">
<input type="button" id="create" value="create">
<input type="button" id="save" value="save">
<input type="button" id="read" value="read">
<input type="button" id="edit" value="edit">
<input type="button" id="update" value="update">
<input type="button" id="delete" value="delete">

<script>
    $(function(){
   
        $('#index').click(function(){
   
            $.ajax({
   
                "url":"/news",
                "type":"get",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        });
        $('#create').click(function(){
   
            $.ajax({
   
                "url":"/news/create",
                "type":"get",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        })
        $('#save').click(function(){
   
            $.ajax({
   
                "url":"/news",
                "type":"post",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        })
        $('#read').click(function(){
   
            $.ajax({
   
                "url":"/news/33",
                "type":"get",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        })
        $('#edit').click(function(){
   
            $.ajax({
   
                "url":"/news/33/edit",
                "type":"get",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        });
        $('#update').click(function(){
   
            $.ajax({
   
                "url":"news/33",
                "type":"put",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        })
        $('#delete').click(function(){
   
            $.ajax({
   
                "url":"news/33",
                "type":"delete",
                "data":"",
                "dataType":"json",
                "success":function(res){
   
                    console.log(res);
                }
            })
        })
    })
</script>
</body>
</html>  

3、请求伪装

部分客户端(比如低版本浏览器)可能仅支持get请求、post请求、不支持delete请求和put请求。

TP框架提供了对“请求伪装”的支持,可以使用post请求携带_method参数,伪装成其他请求。

比如 使用ajax的post请求伪装put请求

public/api.html中添加以下代码

 $('#post-to-update').click(function(){
 
            $.ajax({
 
                "url":"news/33",
                "type":"post",
                "data":"_method=put",
                "dataType":"json",
                "success":function(res){
 
                    console.log(res);
                }
            })
        })
        $('#post-to-delete').click(function(){
 
            //访问delete方法
            $.ajax({
 
                "url":"news/33",
                "type":"post",
                "data":"_method=delete",
                "dataType":"json",
                "success":function(res){
 
                    console.log(res);
                }
            })
        })  

4、Restful常用的资源路由

新增页面展示create方法和修改页面edit方法一般可以不用。

标识

请求类型

生成路由规则

对应操作方法(默认)

备注

index

GET

news

index

查询多条数据(列表)

read

GET

news/:id

read

查询一条数据(详情、修改页面展示)

save

POST

news

save

新增一条数据

update

PUT

news/:id

update

修改一条数据

delete

DELETE

news/:id

delete

删除一条数据

5、实际开发中的Restful

Restful接口通常返回的是完整的数据模型,粒度过于粗,对客户端不友好(客户端可能只需要其中一小部分字段)。

Restful典型使用场景:开放API(各种开放平台的数据api)。开放API之所以开放,就是因为不知道也不关心客户端需要什么返回结果。直接返回完整的数据,好处是通用。

实际开发中,通常都是内部接口开发,需求非常明确,所以一般都是灵活借鉴Restful中的优点,结合自己的实际情况,来设计自己的内部api,在基本的增删改查接口之外,通常会设计一些业务接口(根据业务逻辑需要,一个接口中对多个资源的数据进行整合再返回。)

四、服务端CURL请求

服务端与服务端之间,也存在接口编程

比如我们网站服务端,需要发送短信、发送邮件、查询快递等,都需要调用第三方平台的接口。

1、php中发送请求

1、file_get_contents函数:传递完整的url参数 通常是get请求,有返回值(地址中的输出)。

2、curl请求方式(PHP的curl函数库):php中比较规范的一种发送请求方式。

2、CURL函数库

Curl函数库的使用流程:

1、使用curl_init初始化请求会话

2、使用curl_setopt设置请求一些选项

3、使用curl_exec执行,发送请求

4、使用curl_close关闭请求会话

3、封装请求函数

封装一个函数用来发送curl请求

在application/common.php中封装一个函数curl_request

使用curl函数库的前提:

1、在php.ini中开启php_curl扩展(必须开启)

2、建议在php.ini中开启php_openssl扩展(本身不是curl必须的,是调用一些第三方接口需要的)

3、如果以上操作重启apache后,curl还是不能用,需要将php安装目录设置到环境变量。

 if(!function_exists('curl_request')){
 
    function curl_request($url,$type=false,$params=[],$https=false){
 
        //调用curl_init()初始化请求
        $ch= curl_init($url);
        //调用curl_setopt()设置请求选项
        if($type){
 
            //true发送post请求 false默认发送get请求
            //post请求 设置请求方式
            curl_setopt($ch,CURLOPT_POST,true);
            //设置请求参数
            curl_setopt($ch,CURLOPT_POSTFIELDS,$params);
        }
        //如果是https请求 需要禁止从服务器端验证本地的证书
        if($https){
 
            curl_setopt($ch,CURLOPT_PROXY_SSL_VERIFYPEER,true);
        }
        //调用curl_exec()发送请求 获取结果
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
        $res=curl_exec($ch);
        //调用curl_close() 关闭请求
        curl_close($ch);

        return $res;
    }
}  

测试结果:

5、curl请求错误调试

curl_errno函数返回错误码

curl_error函数返回错误信息

 //模拟本地方法发送请求调用第三方
    public function testrequest(){
 
        //接口地址 
        $url="#34;;
        //请求方式get
        //请求参数 id page
        //$params=['id'=>200,'page'=>10];
        /*$url.='?id=100&page=10';
        //发送请求
        $res=curl_request($url);
        dump($res);die;*/

        //请求方式post
        //请求参数 id page
        $params=['id'=>100,'page'=>10];
        //发送请求
        //$res=curl_request($url,true,$params,false);
        $res=curl_request($url,true,$params);
        //结果的处理
        if(!$res){
 
            echo '请求错误';die;
        }
        //解析结果 $res='{"code"=>200,"msg"=>"success","data"=>{}}';
        $arr=json_decode($res,true);  //把json转为数组
        dump($arr['data']);
        dump($res);die;
    }  

五、快递查询

1、接口说明

提供快递查询的第三方平台很多,比如快递100、聚合数据、百度云、阿里云、腾讯云等等。

2、项目使用

 public function kuaidi(){
 
        $url='#39;;
        //请求方式get
        //请求参数 拼接到url中
        //发送请求
        $res=curl_request($url);
        //对结果进行处理
        if(!$res){
 
            echo '请求错误';die;
        }
        //解析数据 json格式字符串
        $arr=json_decode($res,true);
        if($arr['success']==false){
 
            echo $arr['reason'];die;
        }
        //获取物流数据
        $list=$arr['data'];
        //dump($list);
        echo '时间-------------进度<br>';
        foreach ($list as $v){
 
            echo $v['time'],'----------',$v['context'],'<br>';
        }
        die;
    }  

六、接口文档

1、接口内容

接口名称

场景说明

接口说明

请求参数

响应参数

错误码

2、请求参数内容

字段名

是否必填

类型

示例值

描述

3、响应参数内容

字段名称

描述

返回示例

4、错误码内容

名称

描述

原因

解决方案

1.2、登录接口

1、请求地址

post/login

用于根据用户名,密码进行登录

2、请求参数

名称

类型

必填

备注

username

string

用户名:admin

password

string

密码:123456

code

string

验证码

uniqid

string

验证码标识

3、返回数据

名称

备注

token

token令牌

user_id

用户id

username

用户名

nickname

用户昵称

email

用户邮箱

4、返回示例

 {
"code":200,
"msg":"success",
"data":{
	 "token":"admslkfnlskawjrqwwiepfe",
	 "user_id":"54866",
	"username":"admin",
	"nickname":"麦克",
	"email":"674684@qq.com"
  }
}  

5、改造之前的商品保存方法

 public function save2(Request $request)
    {
 
        //接收数据
        $params = $request->param();
        //定义验证规则
        $rule = [
            'goods_name' => 'require',
            'goods_price' => 'require|float|gt:0',
            'goods_number' => 'require|integer|gt:0'
        ];
        //2定义错误提示信息(可选)
        $msg = [
            'goods_name.require' => '商品名称不能为空',
            'goods_price.require' => '商品价格不能为空',
            'goods_price.float' => '商品价格格式不正确',
            'goods_price.gt' => '商品价格必须大于0',
            'goods_number.require' => '商品数量不能为空',
            'goods_number.gt' => '商品数量必须大于0',
        ];
        //调用控制器的validate方法
        $validate = $this->validate($params, $rule, $msg);
        if ($validate !== true) {
 
            //验证失败,$validate 就是一个字符串错误信息
            return json(['code'=>401,'msg'=>$validate,'data'=>[]]);
        }
        //文件上传
        $params['goods_logo']=$this->upload_logo();
        //添加数据到数据表 第二个参数true表示过滤非数据表字段
        $data=\app\admin\model\Goods::create($params, true);
        return json(['code'=>200,'msg'=>'success','data'=>$data]);
    }  

项目搭建流程

1、安装部署tp框架(解压压缩包、配置虚拟站点)(主域名、子域名,比如www.pyg.com和adminapi.pyg.com)

2、模块划分(后台模块admin、前台模块home、后台接口模块adminapi、公共模块common)

3、admin模块、home模块、adminapi模块、有默认的控制器方法,可以访问。common模块下只需要mode模型目录

4、路由配置:adminapi模块 配置域名路由

5、尝试,对adminapi模块,创建一个Base控制器,定义ok方法和fail方法,用于快捷返回结果数据

比如:

 失败时,以下两行代码 效果一样
return json(['code'=>401,'msg'=>'参数错误','data'=>[]]);
//$this->fail(401,'参数错误')

成功时,以下两行代码 效果一样
return json(['code'=>200,'msg'=>'success','data'=>$data]);
//$this->ok($data)  

文章来源:智云一二三科技

文章标题:RestFul接口设计,手把手带你学会

文章地址:https://www.zhihuclub.com/153001.shtml

关于作者: 智云科技

热门文章

网站地图