ThinkPHP5.0 Restful API 开发流程及小技巧

最近学习了七月老师的ThinkPHP+小程序的实战课程,对用于ThinkPHP开发Rest api接口有了更深的体会,课程中七月老师的清晰的模块化编程思想也给我有了很大的感触。希望通过此篇文章整理课程开发思路的同时,也能给对这方面有学习兴趣的同学提供些许帮助。


一、要学习什么是 RESTful API 首先我们得明白什么是REST?

简单来说:REST是所有Web应用都应该遵守的架构设计指导原则。 英文全词Representational State Transfer,翻译是”表现层状态转化”。

面向资源 是REST最明显的特征,对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。(7个HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)。

简单来说就是将服务器的数据看做是资源,而RESTFUL API 就是给外部使用改变资源的一种操作方法,其中符合REST架构设置是RESTFUL API 最大的特点。其中比较典型的就是HTTP协议。

关于rest 的思想,有兴趣的同学可以参考阅读以下文章

理解本身的REST架构风格
http://www.infoq.com/cn/articles/understanding-restful-style/

理解RESTful架构
http://www.ruanyifeng.com/blog/2011/09/restful.html

Restful API设计指南
http://www.ruanyifeng.com/blog/2014/05/restful_api.html


二、ThinPHP5(以下简称TP5)RESTFUL API 开发流程及注意点


**1. 设置API Route **

在TP5 中通过route.php 即可进行路由的操作,出于安全和代码迭代考虑,应注意以下点:

  • 添加API 版本目录
  • 指定路由访问方式 get/post
  • 接口参数过滤
  • API 路由接口分组

示例代码 :

//Route::rule('路由表达式', '路由地址', '请求类型', '路由参数(数组)', '变量规则(数组)');
Route::get('api/:version/Theme/:id', 'api/:version.Theme/getComplexOne',[],['id'=>'\d+'] );

ThinkPHP5.0 Restful API 开发流程及小技巧_第1张图片


2.编写控制器

示例代码:

 /*
     * 获取product
     * @url /theme/:id
     */
    public function getComplexOne($id){
        //调用自定义验证
        (new IDMustBePostiveInt())->goCheck();//着重点
        //调用模型操作方法
        $theme = ThemeModel::getThemeWithProducts($id);
        if (!$theme){
            //抛出自定义异常
            throw new ThemeException();//着重点
        }
        return $theme;
    }

通过MVC的架构和基于TP5提供 Validate 和 Exception 编写的 自定义验证错误反馈,只需要通过寥寥几行代码,就可以完成控制器逻辑的编写,这无论对工作量来说,还是以后调优以及代码的可阅读性,都是大大的提高,下面着重说一下,自定义验证错误反馈


3.编写自定义验证类 Validate

目录结构:
ThinkPHP5.0 Restful API 开发流程及小技巧_第2张图片

示例代码

IDMustBePostiveInt.php

编写自定义验证器,如这个验证器为ID必须是正整数,在任何需要ID验证时就都可以使用。

namespace app\api\validate;

class IDMustBePostiveInt extends BaseValidate
{
    protected $rule = [
        'id' => 'require|isPositiveInteger',
    ];
    protected $message = [
      'id' => 'id必须是正整数'
    ];
}

BaseValidate.php

编写自定义验证器,可以扩展TP5验证库,主要存放公用的验证方法,方便调用。

namespace app\api\validate;

use think\Validate;

class BaseValidate extends Validate
{
	//进行参数校验
    public function goCheck()
    {
        // 获取http参数
        //参数校验
        $request = Request::instance();
        $params = $request->param();

        $result = $this->batch()->check($params);
        if (!$result) {
            $e = new ParameterException([
                'msg' => $this->error,
                /*'code'=> 400,
                'errorCode' => 1002*/
            ]);
            throw $e;
        } else {
            return true;
        }
    }

    //判断是否是正整数
    protected function isPositiveInteger($value, $rule = '', $data = '', $field = '')
    {
        if (is_numeric($value) && is_int($value + 0) && ($value + 0) > 0) {
            return true;
        } else {
            return false;
        }
    }
}

在日常工作中,通过会使用到参数验证,这一点在API开发中尤为重要,可以大大提高接口的安全性,但是往往TP5自带的Validate 验证方法是不够的,通过编写验证器扩展,可以圆满的补充这一点,而且也大大提高了代码的复用性,减少了工作量。


4.编写自定义错误类 Exception

文件结构:
ThinkPHP5.0 Restful API 开发流程及小技巧_第3张图片

示例代码:

ThemeException .php

自定义错误类,可指定返回的错误信息

namespace app\lib\exception;

class ThemeException extends BaseException
{
    // HTTP 状态码 400,200
    public $code = 400;
    // 错误信息
    public $msg = '请求的主题不存在';
    //自定义错误码
    public $errorCode = 30000;
}

BaseException .php

存放默认反馈信息,通过动态修改其中的默认信息,达到动态反馈的效果。

namespace app\lib\exception;

use think\Exception;

class BaseException extends Exception
{
    // HTTP 状态码 400,200
    public $code = 400;
    // 错误信息
    public $msg = '参数错误';
    //自定义错误码
    public $errorCode = 10000;
	
    public function __construct($params = [])
    {
        if (!is_array($params))
        {
            return;
//            throw new Exception('参数必须是数组');
        }
        
        if (array_key_exists('code', $params))
        {
            $this->code = $params['code'];
        }
        
        if (array_key_exists('msg', $params))
        {
            $this->msg = $params['msg'];
        }
        
        if (array_key_exists('errorCode', $params))
        {
            $this->errorCode = $params['errorCode'];
        }
    }
}

在API开发中,接口的错误反馈尤为重要,可以为产品提供更准确的信息,通常与之相对应的还有一张API反馈信息表,通过查询该表,前端人员可以快速有效的找准错误。而对服务器本身的错误而言,通常是不需要反馈给客户端的,通过编写自定义反馈类,也可以做到这一点。


5.编写模型及关联

示例代码:

Theme.php

作用:编写关联模型和数据库逻辑操作,指定需要查询的字段,等等。

namespace app\api\model;

class Theme extends BaseModel
{
    //关联模型
    public function topicImg(){
        return $this->belongsTo('Image','topic_img_id','id');
    }

    public function headImg()
    {
        return $this->belongsTo('Image','head_img_id','id');
    }
	
    public function products(){
        return $this->belongsToMany('product','theme_product','product_id','theme_id');
    }
	
    public static function getThemeWithProducts($id){
	    //使用关联模型查询
        $theme = self::with('products,topicImg,headImg')->find($id);
        return $theme;
    }
}

BaseModel .php

作用:存放公用的模型修改方法,在这里为imgUrl的前缀修改。

namespace app\api\model;

use think\Model;

class BaseModel extends Model
{
    //读取更改img模型的url值--读取器
    protected function prefixImgUrl($value,$data){
        $finalUrl = $value;
        if ($data['from'] == 1)
        {
            $finalUrl = config('setting.img_prefix').$value;
        }
        return $finalUrl;
    }
}

Image.php

指定对ImageUrl前缀。

namespace app\api\model;

class Image extends BaseModel
{
    //隐藏不需要返回的字段
//    protected $hidden = ['delete_time','id','update_time','from'];
    protected $visible = ['url'];
    //读取更改img模型的url值--读取器
    public function getUrlAttr($value,$data){
        return $this->prefixImgUrl($value,$data);
    }
}

至此,一个结构优美,代码复用性高的API开发大框就出现规模了,篇幅有限,有许多小的知识点如SerService层,Token 编写,缓存等就不在一一赘述。

你可能感兴趣的:(后端技术,TinkPHP,的项目开发)