tp6 API开发笔记01-准备工作

894 阅读1分钟

部署

1.安装TP6稳定版

composer create-project topthink/think api_service

2.URL重写

location / {
	if (!-e $request_filename){
		rewrite  ^(.*)$  /index.php?s=$1  last;   break;
	}
}

3.安装多应用模式扩展think-multi-app

composer require topthink/think-multi-app

4.创建应用

php think build api

5.配置路由

修改路由配置 开启强制路由模式 config/route.php

// 是否强制使用路由
'url_route_must'        => true,

6.API版本控制

controller目录新建文件夹v1 创建控制器 Index.php

image.png

<?php

namespace app\api\controller\v1;

class Index
{
    public function index()
    {
        return 'ok';
    }
}

创建路由测试,将根目录的route目录复制一份到api目录,编辑app.php

<?php

use think\facade\Route;

// 测试
Route::rule(':version/index', ':version.Index/index');

访问 http://127.0.0.1:81/api/v1/index

image.png

API统一返回格式

应用目录新建目录common,将app目录下的BaseController.php移动到common目录,修改命名空间,删除不需要的代码片段,所有控制器都继承这个文件。

<?php
namespace app\api\common;

use think\App;

/**
 * 控制器基础类
 * @package app\api\common
 */
abstract class BaseController
{
    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [];

    /**
     * 构造方法
     * @access public
     * @param App $app 应用对象
     */
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;
    }
}

封装两个公共静态方法方便调用:showResCodeshowResCodeWithOutData,分别用于有数据和无数据返回时的使用场景。

/**
 * API统一数据返回
 * @param string $msg 提示信息
 * @param array $data 数据包
 * @param string $type 数据类型 json
 * @param array $header 设置响应头
 * @param int $code HTTP状态码 200
 * @return Response
 */
public static function showResCode($msg = '请求成功', $data = [], $type = 'json', $header = [], $code = 200)
{
    $data = [
        'msg' => $msg,
        'data' => $data
    ];
    return Response::create($data, $type, $code)->header($header);
}

/**
 * API统一无数据返回
 * @param string $msg 提示信息
 * @param string $type 数据类型 json
 * @param array $header 设置响应头
 * @param int $code HTTP状态码 200
 * @return Response
 */
public static function showResCodeWithOutData($msg = '请求成功', $type = 'json', $header = [], $code = 200)
{
    return self::showResCode($msg, [], $type, $header, $code);
}
return self::showResCode('数据列表', [
    'total' => 1,
    'pageNo' => 1,
    'pageNum' => 15,
    'list' => [
        'id' => 1,
        'name' => '张三'
    ]
]);

image.png

return self::showResCodeWithOutData('提交成功');

image.png

API统一管理业务状态码

config配置目录新建文件status_code.php,这里我使用的是常量的方式,在编辑器中可以关键词联想比较方便。

<?php
/**
 * 业务状态码
 * 业务状态码 统一 ERR开头
 * HTTP状态码 统一 HTTP开头
 */

// 异常默认状态码
const ERR_DEFAULT = 999;
// 业务异常默认HTTP状态码
const HTTP_ERR_DEFAULT = 400;
// 框架内部异常状态码
const HTTP_ERR_FRAMEWORK = 500;

API异常错误处理

TP6官方文档异常处理 www.kancloud.cn/manual/thin…

默认安装应用后,TP6已经内置了一个app\ExceptionHandle异常处理类,直接修改该类的相关方法即可完成应用的自定义异常处理机制。

common目录创建BaseException.php

<?php

namespace app\api\common;


class BaseException extends \Exception
{
    /**
     * @var int 默认状态码
     */
    public $code = HTTP_ERR_DEFAULT;

    /**
     * @var string 错误信息
     */
    public $msg = '接口异常';

    /**
     * @var int 错误状态码
     */
    public $errorCode = ERR_DEFAULT;

    /**
     * BaseException constructor.
     * @param array $params
     */
    public function __construct(array $params = [])
    {
        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异常,在框架异常处理类做出相应的捕获处理

<?php
// 应用公共文件
use app\api\common\BaseException;

/**
 * API异常输出
 * @param string $msg 错误信息
 * @param int $errorCode 错误代码
 * @param int $code 状态码
 * @throws BaseException
 */
function ApiException($msg = '接口异常', $errorCode = 999, $code = 400)
{
    throw new BaseException([
        'code' => $code,
        'msg' => $msg,
        'errorCode' => $errorCode
    ]);
}

修改框架内置异常错误处理类app\ExceptionHandle的render方法

/**
 * Render an exception into an HTTP response.
 *
 * @access public
 * @param \think\Request   $request
 * @param Throwable $e
 * @return Response
 */
public function render($request, Throwable $e): Response
{
    // 添加自定义异常处理机制

    // 其他错误交给系统处理
    return parent::render($request, $e);
}

框架自带的错误处理对API来说并不友好,在正常情况下API的返回应该统一格式,所以这里我将异常错误信息统一输出为JSON格式,在本地调试模式下显示框架原本的错误显示,方便查看和定位错误。

/**
 * Render an exception into an HTTP response.
 *
 * @access public
 * @param \think\Request   $request
 * @param Throwable $e
 * @return Response
 */
public function render($request, Throwable $e): Response
{
    // 添加自定义异常处理机制
    if ($e instanceof BaseException) {
        $this->code = $e->code;
        $this->msg = $e->msg;
        $this->errorCode = $e->errorCode;
    } else {
        //调试模式下 输出框架默认错误提示
        if (env('APP_DEBUG')) return parent::render($request, $e);
        $this->code = HTTP_ERR_FRAMEWORK;
        $this->msg = $e->getMessage();
        $this->errorCode = ERR_DEFAULT;
    }
    return json([
        'msg' => $this->msg,
        'errorCode' => $this->errorCode
    ], $this->code);
}

手动抛出API异常

新增业务状态码 ERR_NOT_LOGIN

// 未登录
const ERR_NOT_LOGIN = 1001;
ApiException('您还没有登录,请先登录', ERR_NOT_LOGIN);

image.png

系统异常捕获处理

在本地开启调试模式下,将显示框架原有的html页面

image.png

待续...