一个简单的接口开发实例

一个简单的接口开发实例

文章目录

  • 一个简单的接口开发实例
    • 0. 写在前面
    • 1. 开发前的准备
      • 1.1 预备知识
      • 1.2 开发环境
      • 1.3 使用软件及笔者使用版本
      • 1.4 软件下载安装及使用教程
        • 1.4.1 xampp:
        • 1.4.2 netbeans:
        • 1.4.3 postman:
        • 1.4.4 navicat:
    • 2. 编写实例
      • 2.1 案例说明
      • 2.2 案例分析
        • 2.2.1 建立数据库和数据表
        • 2.2.2 需要接口
      • 2.3 相关文档
        • 2.3.1 数据字典
          • 2.3.1.1 **用户表(user)**
          • 2.3.1.2 **便签表(note)**
        • 2.3.2 接口文档
          • 2.3.2.1 **错误码**
          • 2.3.2.2 **用户功能接口**
            • 2.3.2.2.1 用户注册
            • 2.3.2.2.2 用户登录
            • 2.3.2.2.3 用户注销
            • 2.3.2.2.4 修改密码
          • 2.3.2.3 **便签功能接口**
            • 2.3.2.3.1 添加便签
            • 2.3.2.3.2 删除便签
            • 2.3.2.3.3 修改便签
            • 2.3.2.3.4 查询便签列表
            • 2.3.2.3.5 查询便签内容
      • 2.4 项目实现
        • 2.4.1 项目准备
          • 2.4.1.1 **启动apache和mysql**
          • 2.4.1.2 **添加notes数据库**
          • 2.4.1.3 **建立php项目**
          • 2.4.1.4 **添加文件夹和php文件**
          • 2.4.1.5 **添加.htaccess文件**
        • 2.4.2 配置数据库连接(conf.php, db.php)
          • 2.4.2.1 **编辑conf.php**
          • 2.4.2.2 **编辑db.php**
        • 2.4.3 编辑错误码类和工具类(Errors.php, Tools.php)
          • 2.4.3.1 **编辑Errors.php**
          • 2.4.3.2 **编辑Tools.php**
        • 2.4.4 编辑启动类(Rest.php)
          • 2.4.4.1 编辑Rest.php
        • 2.4.5 编辑api启动文件index.php
          • 2.4.5.1 编辑index.php
        • 2.4.6 编辑用户类(User.php)
          • 2.4.6.1 **添加User类并编写基本内容**
          • 2.4.6.2 **User.php添加相关功能函数后**
          • 2.4.6.3 修改index.php文件
          • 2.4.6.4 修改Rest.php文件
        • 2.4.7 编写便签类(Note.php)
          • 2.4.7.1 添加Note类并编写基本内容
          • 2.4.7.2 Note.php添加相关功能函数
          • 2.4.7.3 修改index.php文件
          • 2.4.7.4 修改Rest.php文件
    • 3. 接口测试
      • 3.1 项目准备
      • 3.2 用户接口功能测试
        • 3.2.1 **建立user表**
        • 3.2.2 **用户注册**
        • 3.2.3 **用户登录**
        • 3.2.4 **用户修改密码**
        • 3.2.5 **用户注销**
      • 3.3 便签接口功能测试
        • 3.3.1 建立note表
        • 3.3.2 添加便签
        • 3.3.3 修改便签
        • 3.3.4 删除便签
        • 3.3.5 查询便签列表
        • 3.3.6 查询便签内容
      • 3.4 生成在线接口文档
      • 3.5 导出接口集合的JSON文件
      • 3.6 导入接口集合的JSON文件
    • 4. 总结
    • 5. 附录
      • 5.1 SQL学习链接
      • 5.2 PHP学习链接
      • 5.3 HTTP相关链接
      • 5.4 项目模板链接
      • 5.5 完整项目链接
      • 5.6 接口开发学习链接

0. 写在前面

​ 此篇文章主要是通过一个简单案例的后端接口开发过程,介绍一种接口开发方式,作为笔者本人的一个阶段性接口开发学习经验总结。其中案例是一个便签的相关接口,包含对用户和便签的信息管理。因为笔者本人能力所限,难免有差错,还希望读者能够对不正确的地方进行指正。文章也可在笔者的个人博客上查看:https://blog.csdn.net/ice_bear221/article/details/125355144

1. 开发前的准备

1.1 预备知识

  1. 学习过面向对象语言的知识
  2. 学习过SQL相关的知识

说明:

​ 初学阶段不必掌握很多,遇到问题及时搜索,相关内容在附录中也有一些学习链接

1.2 开发环境

  1. 数据库使用mysql
  2. 服务器使用apache
  3. 接口语言使用php

1.3 使用软件及笔者使用版本

  1. xampp v3.2.4:集成开发环境,包含apache、mysql、php等运行环境;
  2. netbeans v12.0:项目代码编辑器
  3. postman v9.20:接口测试、api文档生成工具
  4. navicat v15:数据库图形化管理工具

说明:

​ 也可以选择其他具有上述功能的软件。

1.4 软件下载安装及使用教程

1.4.1 xampp:

https://www.freesion.com/article/952678790/

1.4.2 netbeans:

http://www.cxfeng.com/soft/79220.html

https://blog.csdn.net/weixin_34618077/article/details/115638512

1.4.3 postman:

https://blog.csdn.net/weixin_42306958/article/details/122155484

https://blog.csdn.net/H176Nhx7/article/details/120320235

1.4.4 navicat:

https://www.pianshen.com/article/8072692518/

https://www.fujieace.com/navicat/15-for-mysql.html

说明:

​ 因为笔者的电脑已经配置了一些环境,并未对上述链接内容进行验证,如果安装过程出现问题,也请自行在网上查找相关的软件安装教程。

2. 编写实例

2.1 案例说明

​ 实现一个便签程序的后端接口。

​ 用户可以进行账号注册、账号注销、登录,以及修改密码。

​ 用户登录后可以添加、删除、修改、查询便签列表、查看便签内容。

​ 便签包含标题、内容、一张图片,其中标题不能为空,内容和图片可以为空。

2.2 案例分析

2.2.1 建立数据库和数据表
- 建立项目数据库notes
- 在notes中建立两张数据表user和note,用于存储用户信息和便签信息
- user表包含(用户id,账号,密码)
- note表包含(便签id,用户id,标题,内容,图片url,创建时间)
2.2.2 需要接口
- 用户接口
	- 注册
	- 登录
	- 注销
	- 修改密码
	
- 便签接口
	- 添加便签
	- 删除便签
	= 修改便签
	- 根据用户id查询便签列表
	- 根据便签id查询便签内容

2.3 相关文档

2.3.1 数据字典
2.3.1.1 用户表(user)
字段 含义 类型 大小 是否可为空 默认值 说明
uid 用户id int 主键
account 账号 string 11 手机号
password 密码 string [6, 20] 此处采用明文存储
2.3.1.2 便签表(note)
字段 含义 类型 大小 是否可为空 默认值 说明
nid 便签id int 主键
uid 用户id int 用户表外键
title 标题 string 30
content 内容 string 200 null
imgUrl 图片url string 200 null
createTime 创建时间 datetime 创建或修改后的时间
2.3.2 接口文档
2.3.2.1 错误码
errCode errInfo
0 成功
1 请求资源不存在
2 请求方法不允许
3 请求资源不允许
4 请求功能错误
5 请求参数错误
6 请求方法错误
7 数据表创建出错
8 sql语句执行出错
9 文件类型错误
10 文件大小错误
11 存储文件出错
10001 用户id不能为空
10002 账号重复
10003 缺少账号
10004 两次密码不一致
10005 账号或密码错误
10006 用户不存在
10007 密码错误
10008 缺少密码
10009 缺少确认密码
10010 缺少新密码
10101 便签id不能为空
10102 缺少标题
10103 便签不存在
10104 缺少时间
2.3.2.2 用户功能接口
2.3.2.2.1 用户注册
- 用户注册
请求地址:http://localhost/notes/user/register
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
    "account": "12345678910",
    "password": "123456",
    "rePassword": "123456"
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "注册成功"
}

失败:
{
    "errCode": 10003,
    "errCode": "缺少账号"
}
{
    "errCode": 10004,
    "errCode": "两次密码不一致"
}
{
    "errCode": 10008,
    "errCode": "缺少密码"
}
{
    "errCode": 10009,
    "errCode": "缺少确认密码"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.2.2 用户登录
- 用户登录
请求地址:http://localhost/notes/user/login
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
    "account": "12345678910",
    "password": "123456"
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "登录成功",
    "data": {
        "uid": 1,
        "account": "12345678910"
    }
}

失败:
{
    "errCode": 10003,
    "errCode": "缺少账号"
}
{
    "errCode": 10008,
    "errCode": "缺少密码"
}
{
    "errCode": 10005,
    "errCode": "账号或密码错误"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.2.3 用户注销
- 用户注销
请求地址:http://localhost/notes/user/logout
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
	"uid": 1,
    "password": "123456"
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "注销成功",
}

失败:
{
    "errCode": 10001,
    "errCode": "用户id不能为空"
}
{
    "errCode": 10008,
    "errCode": "缺少密码"
}
{
    "errCode": 10006,
    "errCode": "用户不存在"
}
{
    "errCode": 10007,
    "errCode": "密码错误"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.2.4 修改密码
- 修改密码
请求地址:http://localhost/notes/user/editPass
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
	"uid": 1,
    "password": "123456",
    "rePassword": "123456",
    "newPassword": "654321"
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "修改成功",
}

失败:
{
    "errCode": 10001,
    "errCode": "用户id不能为空"
}
{
    "errCode": 10008,
    "errCode": "缺少密码"
}
{
    "errCode": 10009,
    "errCode": "缺少确认密码"
}
{
    "errCode": 10010,
    "errCode": "缺少新密码"
}
{
    "errCode": 10006,
    "errCode": "用户不存在"
}
{
    "errCode": 10007,
    "errCode": "密码错误"
}
{
    "errCode": 10004,
    "errCode": "两次密码不一致"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.3 便签功能接口
2.3.2.3.1 添加便签
- 添加便签
请求地址:http://localhost/notes/note/add
请求方式:POST
请求类型:content-Type:multipart/form-data
请求参数:
Content-Disposition: form-data; name="uid" 1
Content-Disposition: form-data; name="title" 这是一个标题
Content-Disposition: form-data; name="content" 这是便签内容
Content-Disposition: form-data; name="createTime" 2022-01-01 01:01:01
Content-Disposition: form-data; name="img"; filename="IMG20191125153658.jpg"
Content-Type: image/jpeg

(data)

响应参数:

成功:
{
    "errCode": 0,
    "errCode": "添加成功",
}

失败:
{
    "errCode": 10001,
    "errCode": "用户id不能为空"
}
{
    "errCode": 10006,
    "errCode": "用户不存在"
}
{
    "errCode": 10102,
    "errCode": "缺少标题"
}
{
    "errCode": 10104,
    "errCode": "缺少时间"
}
{
    "errCode": 10,
    "errCode": "文件大小错误"
}
{
    "errCode": 9,
    "errCode": "文件类型错误"
}
{
    "errCode": 11,
    "errCode": "存储文件出错"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.3.2 删除便签
- 删除便签
请求地址:http://localhost/notes/note/delById
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
	"uid": 1,
    "nid": 1
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "删除成功",
}

失败:
{
    "errCode": 10001,
    "errCode": "用户id不能为空"
}
{
    "errCode": 10101,
    "errCode": "便签id不能为空"
}
{
    "errCode": 10006,
    "errCode": "用户不存在"
}
{
    "errCode": 10103,
    "errCode": "便签不存在"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.3.3 修改便签
- 修改便签
请求地址:http://localhost/notes/note/editByNId
请求方式:POST
请求类型:content-Type:multipart/form-data
请求参数:
Content-Disposition: form-data; name="uid" 1
Content-Disposition: form-data; name="nid" 1
Content-Disposition: form-data; name="title" 这是新标题
Content-Disposition: form-data; name="content" 这是新便签内容
Content-Disposition: form-data; name="createTime" 2022-01-02 10:00:00
Content-Disposition: form-data; name="img"; filename="IMG20191125153658.jpg"
Content-Type: image/jpeg

(data)

响应参数:

成功:
{
    "errCode": 0,
    "errCode": "修改成功"
}

失败:
{
    "errCode": 10101,
    "errCode": "便签id不能为空"
}
{
    "errCode": 10103,
    "errCode": "便签不存在"
}
{
    "errCode": 10001,
    "errCode": "用户id不能为空"
}
{
    "errCode": 10006,
    "errCode": "用户不存在"
}
{
    "errCode": 10102,
    "errCode": "缺少标题"
}
{
    "errCode": 10104,
    "errCode": "缺少时间"
}
{
    "errCode": 10,
    "errCode": "文件大小错误"
}
{
    "errCode": 9,
    "errCode": "文件类型错误"
}
{
    "errCode": 11,
    "errCode": "存储文件出错"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.3.4 查询便签列表
- 查询便签列表
请求地址:http://localhost/notes/note/viewListByUid
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
	"uid": 1,
    "offset": 0,
    "limit": 20
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "查询成功",
    "data": [
        {
            "nid": 1,
            "title": "这是一个标题"
        },
        {
            "nid": 2,
            "title": "新的便签"
        }
    ]
}

失败:
{
    "errCode": 10001,
    "errCode": "用户id不能为空"
}
{
    "errCode": 10006,
    "errCode": "用户不存在"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}
2.3.2.3.5 查询便签内容
- 查询便签内容
请求地址:http://localhost/notes/note/viewByNid
请求方式:POST
请求类型:content-Type:application/json
请求参数:
{
	"nid": 1
}
响应参数:

成功:
{
    "errCode": 0,
    "errCode": "查询成功",
    "data": {
        "nid": 1,
        "title": "这是一个标题",
        "content": "这是便签内容",
        "imgUrl": "http://localhost/notes/uploads/abasdfsdf.jpg",
        "createTime": "2022-01-02 10:00:00"
    }
}

失败:
{
    "errCode": 10101,
    "errCode": "便签id不能为空"
}

{
    "errCode": 10103,
    "errCode": "便签不存在"
}
{
    "errCode": 8,
    "errCode": "sql语句执行错误"
}

2.4 项目实现

2.4.1 项目准备
2.4.1.1 启动apache和mysql

一个简单的接口开发实例_第1张图片

2.4.1.2 添加notes数据库

一个简单的接口开发实例_第2张图片
一个简单的接口开发实例_第3张图片
一个简单的接口开发实例_第4张图片
一个简单的接口开发实例_第5张图片
一个简单的接口开发实例_第6张图片

2.4.1.3 建立php项目

一个简单的接口开发实例_第7张图片
一个简单的接口开发实例_第8张图片
一个简单的接口开发实例_第9张图片
一个简单的接口开发实例_第10张图片

2.4.1.4 添加文件夹和php文件

一个简单的接口开发实例_第11张图片
一个简单的接口开发实例_第12张图片
一个简单的接口开发实例_第13张图片一个简单的接口开发实例_第14张图片
一个简单的接口开发实例_第15张图片
一个简单的接口开发实例_第16张图片
一个简单的接口开发实例_第17张图片
一个简单的接口开发实例_第18张图片
一个简单的接口开发实例_第19张图片
一个简单的接口开发实例_第20张图片
一个简单的接口开发实例_第21张图片
一个简单的接口开发实例_第22张图片
一个简单的接口开发实例_第23张图片

2.4.1.5 添加.htaccess文件

一个简单的接口开发实例_第24张图片
一个简单的接口开发实例_第25张图片

添加如下代码:

# 开启重定向
RewriteEngine on
# 访问的不是文件
RewriteCond %{REQUEST_FILENAME} !-f
# 访问的不是文件夹
RewriteCond %{REQUEST_FILENAME} !-d
# 重定向到访问index.php文件
RewriteRule ^(.*)$ index.php/$1 [L] 

说明:

添加.htaccess文件之前的访问链接为:http://localhost/notes/index.php/user/login

添加.htaccess文件之后的访问链接为:http://localhost/notes/user/login

只要访问的内容不是文件和文件夹,都会重定向到访问:http://localhost/notes/index.php

2.4.2 配置数据库连接(conf.php, db.php)
2.4.2.1 编辑conf.php

    
// 此文件用于保存一些默认配置

define("HOST", 'localhost'); // 配置主机名,本机是localhost或127.0.0.1
define("DBNAME", "notes"); // 项目数据库名,
define("DBUSER", "root"); // 登录数据库用户名
define("DBPASS", ""); // 密码

define("VERSION", "1.0"); // 接口版本
define("DOMAIN", "http://localhost/notes"); // 项目位置

2.4.2.2 编辑db.php


require_once __DIR__."/conf.php"; // 引入conf.php文件
//
// 生成并返回数据库连接对象,用于操作数据库
$db = new PDO("mysql:host=".HOST.";dbname=".DBNAME, DBUSER, DBPASS);
return $db;

2.4.3 编辑错误码类和工具类(Errors.php, Tools.php)
2.4.3.1 编辑Errors.php


/**
 * Description of Errors
 *保存项目错误码
 * @author 1
 */
class Errors {
    // 错误码5位
    // 
    // 系统相关 0-9999
    const OK = 0;
    const REQUEST_IS_NULL = 1;
    const REQUEST_METHOD_NOT_ALLOWED = 2;
    const REQUEST_RESOUTCE_NOT_ALLOWED = 3;
    const REQUEST_FUNCTION_IS_ERROR = 4;
    const REQUEST_PARAMETER_ERROR = 5;
    const REQUEST_METHOD_IS_ERROR = 6;
    const BUILD_TABLE_ERROR = 7;
    const SQL_EXECUTE_ERROR = 8;
    const FILE_TYPE_IS_ERROR = 9;
    const FILE_SIZE_IS_ERROR = 10;
    const STORE_FILE_OCCURRED_ERROR = 11;
    
    
    // 用户类相关 10001-10099
    const USER_ID_CONNOT_NULL = 10001;
    const ACCOUNT_REPEAT = 10002;
    const ACCOUNT_IS_MISSING = 10003;
    const PASSWORD_IS_NOT_SAME = 10004;
    const ACCOUNT_OR_PASSWORD_ERROR = 10005;
    const USER_IS_NOT_EXISTS = 10006;
    const PASSWORD_IS_ERROR = 10007;
    const PASSWORD_IS_MISSING = 10008;
    const REPASSWORD_IS_MISSING = 10009;
    const NEW_PASSWORD_IS_MISSING = 10010;
    
    // 便签类相关 10101-10199
    const NOTE_ID_CONNOT_NULL = 10101;
    const TITLE_IS_MISSING = 10102;
    const NOTE_IS_NOT_EXISTS = 10103;
    const TIME_IS_MISSING = 10104;
}

2.4.3.2 编辑Tools.php


require_once 'lib/conf.php';
/**
 * Description of Tools
 * 封装较常用的函数
 * @author 1
 */
class Tools {
    /**
     * 打印调试信息
     * @param type $message print info
     */
    public static function _debug($message) {
        var_dump($message);
    }
    
    /**
     * 打印json格式信息
     * @param type $errInfo 返回信息
     * @param type $errCode 返回信息提示码
     * @param type $data 返回数据
     */
    public static function printJson($errInfo, $errCode, $data=null) {
        $return["errCode"] = $errCode;
        $return["errInfo"] = $errInfo;
        if (!empty($data))
            $return["data"] = $data;
        else if (!is_null($data))
        {
            $return["data"] = [];
        }
        
        header("Content-Type:application/json;charset:utf-8");
        echo json_encode($return, JSON_PRETTY_PRINT + JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES);
    }
    
    /**
     * 根据检查条件和所给文件类型判断文件是够可接受
     * @param string $type
     * @param int $flag
     * @return bool
     */
    public static function checkFileType($type, $flag) {
        $allowImgType = ["jpg", "jpeg", "png", "bmp"];
        $allowDocType = ["doc", "docx", "ppt", "pptx", "xls", "xlsx", "txt"];
        $allowType = ["jpg", "jpeg", "png", "bmp", 
            "doc", "docx", "ppt", "pptx", "xls", "xlsx", 
            "zip", "7z", "rar", "txt"];
        if ($flag == 0) {
            // 是否满足可接受的所有文件类型
            return in_array($type, $allowType);
        }
        else if ($flag == 1) {
            // 是否满足可接受的图片类型
            return in_array($type, $allowImgType);
        }
    }
    
    /**
     * 检查文件大小是否满足条件
     * @param int $fileSize 待检查文件大小
     * @param int $allowSize 可接受大小
     * @return type
     */
    public static function checkFileSize($fileSize, $allowSize) {
        return $fileSize <= $allowSize;
    }
    
    /**
     * 创建多级文件夹
     * @param type $dirName
     */
    public static function createDir($dirName) {
        if (!file_exists("$dirName")) {
            mkdir($dirName, 0777, true);
        }
    }
    
    /**
     * 存储文件,返回文件url
     * @param string $fileDir 文件存储路径
     * @param string $filename 临时文件地址
     * @param string $fileType 文件类型
     * @return string
     */
    public static function storeFile($fileDir, $filename, $fileType) {
        // 生成文件路径
        $filePath = $fileDir."/".md5($filename).".".$fileType;
        
        // 将临时文件存入目标路径
        if (!move_uploaded_file($filename, $filePath)) {
            // 存储失败后返回空
            return null;
        }
        else {
            // 存储成功
            $url = DOMAIN."/".$filePath;
            return $url;
        }
    }
}

2.4.4 编辑启动类(Rest.php)
2.4.4.1 编辑Rest.php


require_once __DIR__.'/Errors.php';
require_once __DIR__.'/Tools.php';
/**
 * Description of Rest
 *
 * @author 1
 */
class Rest {
    // 设置允许的请求方法和资源
    private $_allowMethod = ["GET", "POST"];
    private $_allowResource = ["user", "note"];
    
    // 请求的方法、资源、功能
    private $_requestMethod;
    private $_requestResource;
    private $_requestFunction;
    
    // 资源类对象
    private $_db;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db) {
        $this->_db = $db;
    }
    
    /**
     * api启动方法
     */
    public function run() {
        try {
            // 获取并检查请求的方法和资源
            $this->setRequestMethod();
            $this->setRequestResource();
            
            // 根据请求的资源分发请求,交给对应的资源类处理
            switch ($this->_requestResource) {
                
                default : {
                    Tools::printJson("请求内容为空", Errors::REQUEST_IS_NULL);
                }
            }
        } catch (Exception $exc) {
            Tools::printJson($exc->getMessage(), $exc->getCode());
        }
    }

    /**
     * 获取post提交的数据
     * @return type array
     * @throws Exception 请求参数错误
     */
    private function getBody() {
        // 获取post请求提交的信息
        $postData = file_get_contents("PHP://input");
        
        // post请求提交的参数不能为空
        if (empty($postData))
        {
            throw new Exception("请求参数错误", Errors::REQUEST_PARAMETER_ERROR);
        }
        
        // 将获取的请求参数进行json解码,用于后续操作
        return json_decode($postData, true);
    }
    
    /**
     * 获取并检查请求的方法
     * @throws Exception 请求方法不被允许
     */
    private function setRequestMethod() {
        // 获取请求方法
        $this->_requestMethod = $_SERVER["REQUEST_METHOD"];
        
        // 检查请求方法是否被允许
        if (!in_array($this->_requestMethod, $this->_allowMethod))
        {
            throw new Exception("请求方法不被允许", Errors::REQUEST_METHOD_NOT_ALLOWED);
        }
    }
    
    /**
     * 获取请求的资源、功能
     * @throws Exception 请求资源不被允许
     */
    private function setRequestResource() {
        // 若访问的rl为http://localhost/notes/user/login,则$_SERVER["PATH_INFO"]为 /user/login
        $path = $_SERVER["PATH_INFO"];
        $params = explode('/', $path);

        $this->_requestResource = $params[1];
        if (!in_array($this->_requestResource, $this->_allowResource))
        {
            throw new Exception("请求资源不被允许", Errors::REQUEST_RESOUTCE_NOT_ALLOWED);
        }
        
        if (!empty($params[2]))
        {
            $this->_requestFunction = $params[2];
        }
    }
}

2.4.5 编辑api启动文件index.php
2.4.5.1 编辑index.php


// 下面引入资源类
require_once './class/Rest.php';

// 下面创建资源对象
$db = require_once './lib/db.php';

// 创建启动类对象,并启动
$api = new Rest($db);
$api->run();
2.4.6 编辑用户类(User.php)

说明:

笔者这里为了方便,没有依次介绍每个功能的编写以及测试,而是将所有的内容放在一起,读者练习时可以在写完一个功能后,先看后面的接口测试,检验接口情况。

2.4.6.1 添加User类并编写基本内容

一个简单的接口开发实例_第26张图片



/**
 * Description of User
 * 用户类功能
 * @author 1
 */
class User {
    private $_db;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db) {
        $this->_db = $db;
    }
}

2.4.6.2 User.php添加相关功能函数后


/**
 * Description of User
 * 用户类功能
 * @author 1
 */
class User {
    private $_db;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db) {
        $this->_db = $db;
    }
    
    /**
     * 创建数据表
     */
    public function buildDb() {
        // 建立用户表
        
        // 检查notes数据库中是否包含user表
        $sql = "select count(1) from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='notes' and TABLE_NAME='user'";
        $sm = $this->_db->prepare($sql);

        // 执行sql语句
        if ($sm->execute()) {
            // 获取执行结果
            $re = $sm->fetch(PDO::FETCH_COLUMN);
            
            //    表不存在,开始建立
            if (!$re) {
                $sql = "create table user  (
                        uId int primary key not null auto_increment comment '用户id',
                        account varchar(11) unique not null comment '手机号',
                        password varchar(20) not null comment '密码'
                      )";
                $sm = $this->_db->prepare($sql);
                if ($sm->execute()) {
                    Tools::printJson("建表成功", Errors::OK);
                } else {
                    Tools::printJson("建表失败", Errors::BUILD_TABLE_ERROR);
                }
            }
            else {
                Tools::printJson("表已经存在", Errors::OK);
            }
        } else {
            Tools::printJson("sql语句执行失败", Errors::SQL_EXECUTE_ERROR);
        }
    }
    
    /**
     * 用户注册
     * @param Object $postData
     * @throws Exception
     */
    public function register($postData) {
        // 检查参数
        if (!key_exists("account", $postData) || empty($postData["account"])) {
            throw new Exception("缺少账号", Errors::ACCOUNT_IS_MISSING);
        }
        if (!key_exists("password", $postData) || empty($postData["password"])) {
            throw new Exception("缺少密码", Errors::PASSWORD_IS_MISSING);
        }
        if (!key_exists("rePassword", $postData) || empty($postData["rePassword"])) {
            throw new Exception("缺少确认密码", Errors::REPASSWORD_IS_MISSING);
        }
        if (!($postData["password"] === $postData["rePassword"])) {
            throw new Exception("两次密码不一致", Errors::PASSWORD_IS_NOT_SAME);
        }
        
        // 将用户信息添加进数据库
        // 注意在每行结尾的"前添加空格,否则可能导致sql语句执行错误
        $sql = "insert into user(account, password) "
                . "values(:account, :password) ";
        
        // 进行预处理
        $sm = $this->_db->prepare($sql);
        
        // 绑定数据
        $sm->bindParam(":account", $postData["account"]);
        $sm->bindParam(":password", $postData["password"]);
        
        // 执行sql语句
        if (!$sm->execute()) {
            throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            Tools::printJson("注册成功", Errors::OK);
        }
    }
    
    /**
     * 用户登录
     * @param type $postData
     * @throws Exception
     */
    public function login($postData) {
        // 检查参数
        if (!key_exists("account", $postData) || empty($postData["account"])) {
            throw new Exception("缺少账号", Errors::ACCOUNT_IS_MISSING);
        }
        if (!key_exists("password", $postData) || empty($postData["password"])) {
            throw new Exception("缺少密码", Errors::PASSWORD_IS_MISSING);
        }
        
        // 查询数据库信息
        $sql = "select uid, account from user "
                . "where account = :account "
                . "and password = :password ";
        
        // 进行预处理
        $sm = $this->_db->prepare($sql);
        
        // 绑定数据
        $sm->bindParam(":account", $postData["account"]);
        $sm->bindParam(":password", $postData["password"]);
        
        // 执行sql语句
        if (!$sm->execute()) {
            throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            // 获取查询结果
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            // 检查结果并返回信息
            if (empty($returnData)) {
                throw new Exception("账号或密码错误", Errors::ACCOUNT_OR_PASSWORD_ERROR);
            }
            else {
                Tools::printJson("登录成功", Errors::OK, $returnData);
            }
        }
    }
    
    /**
     * 修改密码
     * @param type $postData
     * @throws Exception
     */
    public function editPass($postData) {
        // 检查参数
        if (!key_exists("uid", $postData) || empty($postData["uid"])) {
            throw new Exception("用户id不能为空", Errors::USER_ID_CONNOT_NULL);
        }
        if (!key_exists("password", $postData) || empty($postData["password"])) {
            throw new Exception("缺少密码", Errors::PASSWORD_IS_MISSING);
        }
        if (!key_exists("rePassword", $postData) || empty($postData["rePassword"])) {
            throw new Exception("缺少确认密码", Errors::REPASSWORD_IS_MISSING);
        }
        if (!key_exists("newPassword", $postData) || empty($postData["newPassword"])) {
            throw new Exception("缺少新密码", Errors::NEW_PASSWORD_IS_MISSING);
        }
        if (!($postData["password"] === $postData["rePassword"])) {
            throw new Exception("两次密码不一致", Errors::PASSWORD_IS_NOT_SAME);
        }
        
        // 判断用户是否存在,以及查询原密码进行比对
        $sql = "select password from user "
                . "where uid = :uid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            // 检查用户信息
            if (empty($returnData)) {
                throw new Exception("用户不存在", Errors::USER_IS_NOT_EXISTS);
            }
            else {
                if (!($postData["password"] === $returnData["password"])) {
                    throw new Exception("密码错误", Errors::PASSWORD_IS_ERROR);
                }
                else {
                    // 更新用户密码
                    $sql = "update user set password = :newPassword "
                            . "where uid = :uid ";
                    $sm = $this->_db->prepare($sql);
                    $sm->bindParam(":uid", $postData["uid"]);
                    $sm->bindParam(":newPassword", $postData["newPassword"]);
                    
                    if (!$sm->execute()) {
                        throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
                    }
                    else {
                        Tools::printJson("修改成功", Errors::OK);
                    }
                }
            }
        }
    }
    
    /**
     * 用户注销
     * @param type $postData
     * @throws Exception
     */
    public function logout($postData) {
        // 检查参数
        if (!key_exists("uid", $postData) || empty($postData["uid"])) {
            throw new Exception("用户id不能为空", Errors::USER_ID_CONNOT_NULL);
        }
        if (!key_exists("password", $postData) || empty($postData["password"])) {
            throw new Exception("缺少密码", Errors::PASSWORD_IS_MISSING);
        }
        
        // 判断用户是否存在,以及查询原密码进行比对
        $sql = "select password from user "
                . "where uid = :uid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            // 检查用户信息
            if (empty($returnData)) {
                throw new Exception("用户不存在", Errors::USER_IS_NOT_EXISTS);
            }
            else {
                if (!($postData["password"] === $returnData["password"])) {
                    throw new Exception("密码错误", Errors::PASSWORD_IS_ERROR);
                }
                else {
                    // 开启事务,保证下面的sql语句全部执行正确后才修改数据库内容
                    $this->_db->beginTransaction();
                    
                    // 删除用户发布的所有便签,此时还没有添加note数据表,可以先忽略
                    /*
                    $sql = "delete from note where uid = :uid ";
                    $sm = $this->_db->prepare($sql);
                    $sm->bindParam(":uid", $postData["uid"]);
                    
                    if (!$sm->execute()) {
                        // 数据库回滚
                        $this->_db->rollBack();
                        
                        throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
                    }
                     * 
                     */
                    
                    // 删除用户
                    $sql = "delete from user where uid = :uid ";
                    $sm = $this->_db->prepare($sql);
                    $sm->bindParam(":uid", $postData["uid"]);
                    
                    if (!$sm->execute()) {
                        // 数据库回滚
                        $this->_db->rollBack();
                        
                        throw new Exception("sql语句执行错误", Errors::SQL_EXECUTE_ERROR);
                    }
                    else {
                        // 提交数据库操作
                        $this->_db->commit();
                        
                        Tools::printJson("注销成功", Errors::OK);
                    }
                }
            }
        }
    }
}

2.4.6.3 修改index.php文件


// 下面引入资源类
require_once './class/Rest.php';
require_once './class/User.php';    // 引入User类

// 下面创建资源对象
$db = require_once './lib/db.php';
$user = new User($db);  // 创建User资源类对象

// 创建启动类对象,并启动
$api = new Rest($db, $user);
$api->run();
2.4.6.4 修改Rest.php文件


require_once __DIR__.'/Errors.php';
require_once __DIR__.'/Tools.php';
/**
 * Description of Rest
 *
 * @author 1
 */
class Rest {
    // 设置允许的请求方法和资源
    private $_allowMethod = ["GET", "POST"];
    private $_allowResource = ["user", "note"];
    
    // 请求的方法、资源、功能
    private $_requestMethod;
    private $_requestResource;
    private $_requestFunction;
    
    // 资源类对象
    private $_db;
    private $_user;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db, User $user) {
        $this->_db = $db;
        $this->_user = $user;
    }
    
    /**
     * api启动方法
     */
    public function run() {
        try {
            // 获取并检查请求的方法和资源
            $this->setRequestMethod();
            $this->setRequestResource();
            
            // 根据请求的资源分发请求,交给对应的资源类处理
            switch ($this->_requestResource) {
                case "user": {
                    $this->sendUser();
                    break;
                }
                default : {
                    Tools::printJson("请求内容为空", Errors::REQUEST_IS_NULL);
                }
            }
        } catch (Exception $exc) {
            Tools::printJson($exc->getMessage(), $exc->getCode());
        }
    }
    
    
    /**
     * 处理用户业务
     * @throws Exception
     */
    private function sendUser() {
        switch ($this->_requestMethod) {
            case "POST": {
                switch ($this->_requestFunction) {
                    case "buildDb": {
                        $this->_user->buildDb();
                        break;
                    }
                    case "register": {
                        $this->_user->register($this->getBody());
                        break;
                    }
                    case "login": {
                        $this->_user->login($this->getBody());
                        break;
                    }
                    case "editPass": {
                        $this->_user->editPass($this->getBody());
                        break;
                    }
                    case "logout": {
                        $this->_user->logout($this->getBody());
                        break;
                    }
                    default : {
                        Tools::printJson("请求功能不存在", Errors::REQUEST_FUNCTION_IS_ERROR);
                    }
                }
                break;
            }
            default: {
                throw new Exception("该资源没有此方法的接口", Errors::REQUEST_METHOD_IS_ERROR);
            }
        }
    }

    /**
     * 获取post提交的数据
     * @return type array
     * @throws Exception 请求参数错误
     */
    private function getBody() {
        // 获取post请求提交的信息
        $postData = file_get_contents("PHP://input");
        
        // post请求提交的参数不能为空
        if (empty($postData))
        {
            throw new Exception("请求参数错误", Errors::REQUEST_PARAMETER_ERROR);
        }
        
        // 将获取的请求参数进行json解码,用于后续操作
        return json_decode($postData, true);
    }
    
    /**
     * 获取并检查请求的方法
     * @throws Exception 请求方法不被允许
     */
    private function setRequestMethod() {
        // 获取请求方法
        $this->_requestMethod = $_SERVER["REQUEST_METHOD"];
        
        // 检查请求方法是否被允许
        if (!in_array($this->_requestMethod, $this->_allowMethod))
        {
            throw new Exception("请求方法不被允许", Errors::REQUEST_METHOD_NOT_ALLOWED);
        }
    }
    
    /**
     * 获取请求的资源、功能
     * @throws Exception 请求资源不被允许
     */
    private function setRequestResource() {
        // 若访问的rl为http://localhost/notes/user/login,则$_SERVER["PATH_INFO"]为 /user/login
        $path = $_SERVER["PATH_INFO"];
        $params = explode('/', $path);

        $this->_requestResource = $params[1];
        if (!in_array($this->_requestResource, $this->_allowResource))
        {
            throw new Exception("请求资源不被允许", Errors::REQUEST_RESOUTCE_NOT_ALLOWED);
        }
        
        if (!empty($params[2]))
        {
            $this->_requestFunction = $params[2];
        }
    }
}

2.4.7 编写便签类(Note.php)
2.4.7.1 添加Note类并编写基本内容

一个简单的接口开发实例_第27张图片



/**
 * Description of Note
 * 便签类功能
 * @author 1
 */
class Note {
    private $_db;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db) {
        $this->_db = $db;
    }
}

2.4.7.2 Note.php添加相关功能函数


/**
 * Description of Note
 * 便签类功能
 * @author 1
 */
class Note {
    private $_db;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db) {
        $this->_db = $db;
    }
    
    /**
     * 创建数据表
     */
    public function buildDb() {
        // 建立便签表
        
        // 检查notes数据库中是否包含note表
        $sql = "select count(1) from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='notes' and TABLE_NAME='note'";
        $sm = $this->_db->prepare($sql);

        // 执行sql语句
        if ($sm->execute()) {
            // 获取执行结果
            $re = $sm->fetch(PDO::FETCH_COLUMN);
            
            //    表不存在,开始建立
            if (!$re) {
                $sql = "create table note  (
                        nid int primary key not null auto_increment comment '便签id',
                        uid int not null comment '用户id',
                        title varchar(30) not null comment '标题',
                        content varchar(200) null comment '内容',
                        imgUrl varchar(200) null comment '图片url',
                        createTime datetime not null comment '创建或修改后的时间',
                        foreign key(uid) references user(uid)
                      )";
                $sm = $this->_db->prepare($sql);
                if ($sm->execute()) {
                    Tools::printJson("建表成功", Errors::OK);
                } else {
                    Tools::printJson("建表失败", Errors::BUILD_TABLE_ERROR);
                }
            }
            else {
                Tools::printJson("表已经存在", Errors::OK);
            }
        } else {
            Tools::printJson("sql语句执行失败", Errors::SQL_EXECUTE_ERROR);
        }
    }
    
    /**
     * 添加便签
     * @throws Exception
     */
    public function add() {
        // 获取请求参数
        $postData = $_POST;
        $fileData = $_FILES;
        
        // 检查参数
        if (!key_exists("uid", $postData) || empty($postData["uid"])) {
            throw new Exception("用户id不能为空", Errors::USER_ID_CONNOT_NULL);
        }
        if (!key_exists("title", $postData) || empty($postData["title"])) {
            throw new Exception("缺少标题", Errors::TITLE_IS_MISSING);
        }
        if (!key_exists("createTime", $postData) || empty($postData["createTime"])) {
            throw new Exception("缺少时间", Errors::TIME_IS_MISSING);
        }
        
        // 检查用户是否存在
        $sql = "select count(1) 'count' from user "
                . "where uid = :uid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("用户不存在", Errors::USER_IS_NOT_EXISTS);
            }
        }
        
        // 如果含有图片,先保存到文件夹内
        if (!key_exists("img", $fileData) || empty($fileData["img"]) || $fileData["img"]["size"] == 0) {
            $postData["imgUrl"] = null;
        }
        else {
            // 存储图片
            // 检查图片类型
            $type = explode(".", $fileData["img"]["name"]);
            $fileType = $type[count($type) - 1];
            if (!Tools::checkFileType($fileType, 1)) {
                throw new Exception("文件类型错误", Errors::FILE_TYPE_IS_ERROR);
            }
            
            // 检查图片大小,<=8M
            if (!Tools::checkFileSize($fileData["img"]["size"], 8388608)) {
                throw new Exception("文件大小错误", Errors::FILE_SIZE_IS_ERROR);
            }
            
            // 创建图片文件夹,存储图片
            $fileDir = "uploads/img";
            Tools::createDir($fileDir);
            $url = Tools::storeFile($fileDir, $fileData["img"]["tmp_name"], $fileType);
            if (is_null($url)) {
                throw new Exception("存储文件出错", Errors::STORE_FILE_OCCURRED_ERROR);
            }
            $postData["imgUrl"] = $url;
        }
        
        // 保存信息到数据库
        $sql = "insert into note(uid, title, content, createTime, imgUrl) "
                . "values(:uid, :title, :content, :createTime, :imgUrl) ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        $sm->bindParam(":title", $postData["title"]);
        $sm->bindParam(":content", $postData["content"]);
        $sm->bindParam(":createTime", $postData["createTime"]);
        $sm->bindParam(":imgUrl", $postData["imgUrl"]);
        
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            Tools::printJson("添加成功", Errors::OK);
        }
    }
    
    /**
     * 修改便签
     * @throws Exception
     */
    public function editByNid() {
        // 获取请求参数
        $postData = $_POST;
        $fileData = $_FILES;
        
        // 检查参数
        if (!key_exists("uid", $postData) || empty($postData["uid"])) {
            throw new Exception("用户id不能为空", Errors::USER_ID_CONNOT_NULL);
        }
        if (!key_exists("nid", $postData) || empty($postData["nid"])) {
            throw new Exception("便签id不能为空", Errors::NOTE_ID_CONNOT_NULL);
        }
        if (!key_exists("title", $postData) || empty($postData["title"])) {
            throw new Exception("缺少标题", Errors::TITLE_IS_MISSING);
        }
        if (!key_exists("createTime", $postData) || empty($postData["createTime"])) {
            throw new Exception("缺少时间", Errors::TIME_IS_MISSING);
        }
        
        // 检查用户是否存在
        $sql = "select count(1) 'count' from user "
                . "where uid = :uid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("用户不存在", Errors::USER_IS_NOT_EXISTS);
            }
        }
        
        // 检查便签是否存在
        $sql = "select count(1) 'count' from note "
                . "where uid = :uid "
                . "and nid = :nid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        $sm->bindParam(":nid", $postData["nid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("便签不存在", Errors::NOTE_IS_NOT_EXISTS);
            }
        }
        
        // 如果含有图片,先保存到文件夹内
        if (!key_exists("img", $fileData) || empty($fileData["img"]) || $fileData["img"]["size"] == 0) {
            $postData["imgUrl"] = null;
        }
        else {
            // 存储图片
            // 检查图片类型
            $type = explode(".", $fileData["img"]["name"]);
            $fileType = $type[count($type) - 1];
            if (!Tools::checkFileType($fileType, 1)) {
                throw new Exception("文件类型错误", Errors::FILE_TYPE_IS_ERROR);
            }
            
            // 检查图片大小,<=8M
            if (!Tools::checkFileSize($fileData["img"]["size"], 8388608)) {
                throw new Exception("文件大小错误", Errors::FILE_SIZE_IS_ERROR);
            }
            
            // 创建图片文件夹,存储图片
            $fileDir = "uploads/img";
            Tools::createDir($fileDir);
            $url = Tools::storeFile($fileDir, $fileData["img"]["tmp_name"], $fileType);
            if (is_null($url)) {
                throw new Exception("存储文件出错", Errors::STORE_FILE_OCCURRED_ERROR);
            }
            $postData["imgUrl"] = $url;
        }
        
        // 保存信息到数据库
        $sql = "update note set title = :title, content = :content, "
                . "createTime = :createTime, imgUrl = :imgUrl "
                . "where nid = :nid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":nid", $postData["nid"]);
        $sm->bindParam(":title", $postData["title"]);
        $sm->bindParam(":content", $postData["content"]);
        $sm->bindParam(":createTime", $postData["createTime"]);
        $sm->bindParam(":imgUrl", $postData["imgUrl"]);
        
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            Tools::printJson("修改成功", Errors::OK);
        }
    }
    
    /**
     * 查询便签列表
     * @param type $postData
     * @throws Exception
     */
    public function viewListByUid($postData) {
        // 检查参数
        if (!key_exists("uid", $postData) || empty($postData["uid"])) {
            throw new Exception("用户id不能为空", Errors::USER_ID_CONNOT_NULL);
        }
        if (!key_exists("offset", $postData) || empty($postData["offset"])) {
            $postData["offset"] = 0;
        }
        if (!key_exists("limit", $postData) || empty($postData["limit"]) 
                || $postData["limit"] > 20) {
            $postData["limit"] = 20;
        }
        
        // 检查用户是否存在
        $sql = "select count(1) 'count' from user "
                . "where uid = :uid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("用户不存在", Errors::USER_IS_NOT_EXISTS);
            }
        }
        
        // 查询便签列表
        $sql = "select nid, title from note "
                . "where uid = :uid "
                . "limit :offset, :limit ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        $sm->bindParam(":offset", $postData["offset"], PDO::PARAM_INT);
        $sm->bindParam(":limit", $postData["limit"], PDO::PARAM_INT);
        
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetchAll(PDO::FETCH_ASSOC);
            
            Tools::printJson("查询成功", Errors::OK, $returnData);
        }
    }
    
    /**
     * 查询便签内容
     * @param type $postData
     * @throws Exception
     */
    public function viewByNid($postData) {
        // 检查参数
        if (!key_exists("nid", $postData) || empty($postData["nid"])) {
            throw new Exception("便签id不能为空", Errors::NOTE_ID_CONNOT_NULL);
        }
        
        // 检查便签是否存在
        $sql = "select count(1) 'count' from note "
                . "where nid = :nid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":nid", $postData["nid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("便签不存在", Errors::NOTE_IS_NOT_EXISTS);
            }
        }
        
        // 查询便签内容
        $sql = "select nid, title, content, imgUrl, createTime from note "
                . "where nid = :nid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":nid", $postData["nid"]);
        
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            Tools::printJson("查询成功", Errors::OK, $returnData);
        }
    }
    
    /**
     * 删除便签
     * @param type $postData
     * @throws Exception
     */
    public function delById($postData) {
        // 检查参数
        if (!key_exists("uid", $postData) || empty($postData["uid"])) {
            throw new Exception("用户id不能为空", Errors::USER_ID_CONNOT_NULL);
        }
        if (!key_exists("nid", $postData) || empty($postData["nid"])) {
            throw new Exception("便签id不能为空", Errors::NOTE_ID_CONNOT_NULL);
        }
        
        // 检查用户是否存在
        $sql = "select count(1) 'count' from user "
                . "where uid = :uid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("用户不存在", Errors::USER_IS_NOT_EXISTS);
            }
        }
        
        // 检查便签是否存在
        $sql = "select count(1) 'count' from note "
                . "where uid = :uid "
                . "and nid = :nid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        $sm->bindParam(":nid", $postData["nid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            $returnData = $sm->fetch(PDO::FETCH_ASSOC);
            
            if (empty($returnData["count"])) {
                throw new Exception("便签不存在", Errors::NOTE_IS_NOT_EXISTS);
            }
        }
        
        // 删除便签
        $sql = "delete from note "
                . "where uid = :uid "
                . "and nid = :nid ";
        $sm = $this->_db->prepare($sql);
        $sm->bindParam(":uid", $postData["uid"]);
        $sm->bindParam(":nid", $postData["nid"]);
        if (!$sm->execute()) {
            throw new Exception("sql语句执行出错", Errors::SQL_EXECUTE_ERROR);
        }
        else {
            Tools::printJson("删除成功", Errors::OK);
        }
    }
}

2.4.7.3 修改index.php文件


// 下面引入资源类
require_once './class/Rest.php';
require_once './class/User.php';    // 引入User类
require_once './class/Note.php';    // 引入Note类
//
// 下面创建资源对象
$db = require_once './lib/db.php';
$user = new User($db);  // 创建User资源类对象
$note = new Note($db);  // 创建Note资源类对象

// 创建启动类对象,并启动
$api = new Rest($db, $user, $note);
$api->run();
2.4.7.4 修改Rest.php文件


require_once __DIR__.'/Errors.php';
require_once __DIR__.'/Tools.php';
/**
 * Description of Rest
 *
 * @author 1
 */
class Rest {
    // 设置允许的请求方法和资源
    private $_allowMethod = ["GET", "POST"];
    private $_allowResource = ["user", "note"];
    
    // 请求的方法、资源、功能
    private $_requestMethod;
    private $_requestResource;
    private $_requestFunction;
    
    // 资源类对象
    private $_db;
    private $_user;
    private $_note;
    
    /**
     * 构造函数
     * @param PDO $db
     */
    public function __construct(PDO $db, User $user, Note $note) {
        $this->_db = $db;
        $this->_user = $user;
        $this->_note = $note;
    }
    
    /**
     * api启动方法
     */
    public function run() {
        try {
            // 获取并检查请求的方法和资源
            $this->setRequestMethod();
            $this->setRequestResource();
            
            // 根据请求的资源分发请求,交给对应的资源类处理
            switch ($this->_requestResource) {
                case "user": {
                    $this->sendUser();
                    break;
                }
                case "note": {
                    $this->sendNote();
                    break;
                }
                default : {
                    Tools::printJson("请求内容为空", Errors::REQUEST_IS_NULL);
                }
            }
        } catch (Exception $exc) {
            Tools::printJson($exc->getMessage(), $exc->getCode());
        }
    }
    
    /**
     * 处理便签业务
     * @throws Exception
     */
    private function sendNote() {
        switch ($this->_requestMethod) {
            case "POST": {
                switch ($this->_requestFunction) {
                    case "buildDb": {
                        $this->_note->buildDb();
                        break;
                    }
                    case "add": {
                        $this->_note->add();
                        break;
                    }
                    case "editByNid": {
                        $this->_note->editByNid();
                        break;
                    }
                    case "viewListByUid": {
                        $this->_note->viewListByUid($this->getBody());
                        break;
                    }
                    case "viewByNid": {
                        $this->_note->viewByNid($this->getBody());
                        break;
                    }
                    case "delById": {
                        $this->_note->delById($this->getBody());
                        break;
                    }
                    default : {
                        Tools::printJson("请求功能不存在", Errors::REQUEST_FUNCTION_IS_ERROR);
                    }
                }
                break;
            }
            default: {
                throw new Exception("该资源没有此方法的接口", Errors::REQUEST_METHOD_IS_ERROR);
            }
        }
    }
    
    
    /**
     * 处理用户业务
     * @throws Exception
     */
    private function sendUser() {
        switch ($this->_requestMethod) {
            case "POST": {
                switch ($this->_requestFunction) {
                    case "buildDb": {
                        $this->_user->buildDb();
                        break;
                    }
                    case "register": {
                        $this->_user->register($this->getBody());
                        break;
                    }
                    case "login": {
                        $this->_user->login($this->getBody());
                        break;
                    }
                    case "editPass": {
                        $this->_user->editPass($this->getBody());
                        break;
                    }
                    case "logout": {
                        $this->_user->logout($this->getBody());
                        break;
                    }
                    default : {
                        Tools::printJson("请求功能不存在", Errors::REQUEST_FUNCTION_IS_ERROR);
                    }
                }
                break;
            }
            default: {
                throw new Exception("该资源没有此方法的接口", Errors::REQUEST_METHOD_IS_ERROR);
            }
        }
    }

    /**
     * 获取post提交的数据
     * @return type array
     * @throws Exception 请求参数错误
     */
    private function getBody() {
        // 获取post请求提交的信息
        $postData = file_get_contents("PHP://input");
        
        // post请求提交的参数不能为空
        if (empty($postData))
        {
            throw new Exception("请求参数错误", Errors::REQUEST_PARAMETER_ERROR);
        }
        
        // 将获取的请求参数进行json解码,用于后续操作
        return json_decode($postData, true);
    }
    
    /**
     * 获取并检查请求的方法
     * @throws Exception 请求方法不被允许
     */
    private function setRequestMethod() {
        // 获取请求方法
        $this->_requestMethod = $_SERVER["REQUEST_METHOD"];
        
        // 检查请求方法是否被允许
        if (!in_array($this->_requestMethod, $this->_allowMethod))
        {
            throw new Exception("请求方法不被允许", Errors::REQUEST_METHOD_NOT_ALLOWED);
        }
    }
    
    /**
     * 获取请求的资源、功能
     * @throws Exception 请求资源不被允许
     */
    private function setRequestResource() {
        // 若访问的rl为http://localhost/notes/user/login,则$_SERVER["PATH_INFO"]为 /user/login
        $path = $_SERVER["PATH_INFO"];
        $params = explode('/', $path);

        $this->_requestResource = $params[1];
        if (!in_array($this->_requestResource, $this->_allowResource))
        {
            throw new Exception("请求资源不被允许", Errors::REQUEST_RESOUTCE_NOT_ALLOWED);
        }
        
        if (!empty($params[2]))
        {
            $this->_requestFunction = $params[2];
        }
    }
}

3. 接口测试

3.1 项目准备

一个简单的接口开发实例_第28张图片
一个简单的接口开发实例_第29张图片
一个简单的接口开发实例_第30张图片
一个简单的接口开发实例_第31张图片
一个简单的接口开发实例_第32张图片
一个简单的接口开发实例_第33张图片
一个简单的接口开发实例_第34张图片
一个简单的接口开发实例_第35张图片
一个简单的接口开发实例_第36张图片
一个简单的接口开发实例_第37张图片
一个简单的接口开发实例_第38张图片
一个简单的接口开发实例_第39张图片
一个简单的接口开发实例_第40张图片
一个简单的接口开发实例_第41张图片
一个简单的接口开发实例_第42张图片
一个简单的接口开发实例_第43张图片
一个简单的接口开发实例_第44张图片
一个简单的接口开发实例_第45张图片
一个简单的接口开发实例_第46张图片
一个简单的接口开发实例_第47张图片
一个简单的接口开发实例_第48张图片
一个简单的接口开发实例_第49张图片

3.2 用户接口功能测试

3.2.1 建立user表

一个简单的接口开发实例_第50张图片
一个简单的接口开发实例_第51张图片
一个简单的接口开发实例_第52张图片
一个简单的接口开发实例_第53张图片

3.2.2 用户注册

一个简单的接口开发实例_第54张图片
一个简单的接口开发实例_第55张图片
一个简单的接口开发实例_第56张图片
一个简单的接口开发实例_第57张图片
一个简单的接口开发实例_第58张图片

3.2.3 用户登录

一个简单的接口开发实例_第59张图片一个简单的接口开发实例_第60张图片
一个简单的接口开发实例_第61张图片
一个简单的接口开发实例_第62张图片

3.2.4 用户修改密码

一个简单的接口开发实例_第63张图片
一个简单的接口开发实例_第64张图片
一个简单的接口开发实例_第65张图片
一个简单的接口开发实例_第66张图片
一个简单的接口开发实例_第67张图片

3.2.5 用户注销

一个简单的接口开发实例_第68张图片
一个简单的接口开发实例_第69张图片
一个简单的接口开发实例_第70张图片
一个简单的接口开发实例_第71张图片
一个简单的接口开发实例_第72张图片

3.3 便签接口功能测试

3.3.1 建立note表

一个简单的接口开发实例_第73张图片
一个简单的接口开发实例_第74张图片

3.3.2 添加便签

一个简单的接口开发实例_第75张图片
一个简单的接口开发实例_第76张图片
一个简单的接口开发实例_第77张图片
一个简单的接口开发实例_第78张图片
一个简单的接口开发实例_第79张图片

3.3.3 修改便签

一个简单的接口开发实例_第80张图片
一个简单的接口开发实例_第81张图片
一个简单的接口开发实例_第82张图片

3.3.4 删除便签

一个简单的接口开发实例_第83张图片
一个简单的接口开发实例_第84张图片
一个简单的接口开发实例_第85张图片
一个简单的接口开发实例_第86张图片

3.3.5 查询便签列表

一个简单的接口开发实例_第87张图片
一个简单的接口开发实例_第88张图片
一个简单的接口开发实例_第89张图片
一个简单的接口开发实例_第90张图片

3.3.6 查询便签内容

一个简单的接口开发实例_第91张图片
一个简单的接口开发实例_第92张图片
一个简单的接口开发实例_第93张图片

3.4 生成在线接口文档

一个简单的接口开发实例_第94张图片
一个简单的接口开发实例_第95张图片
一个简单的接口开发实例_第96张图片
一个简单的接口开发实例_第97张图片
一个简单的接口开发实例_第98张图片
一个简单的接口开发实例_第99张图片
一个简单的接口开发实例_第100张图片

3.5 导出接口集合的JSON文件

一个简单的接口开发实例_第101张图片
一个简单的接口开发实例_第102张图片
一个简单的接口开发实例_第103张图片
一个简单的接口开发实例_第104张图片

3.6 导入接口集合的JSON文件

一个简单的接口开发实例_第105张图片
一个简单的接口开发实例_第106张图片
一个简单的接口开发实例_第107张图片
一个简单的接口开发实例_第108张图片
一个简单的接口开发实例_第109张图片
一个简单的接口开发实例_第110张图片

4. 总结

  1. 首先了解一些SQL语句的写法以及PHP的语法,初学时不需要完全掌握,遇到问题时,善于使用搜索引擎;
  2. 配置开发环境,使用XAMPP集成环境,使用其中的Apache和MySQL,PHP项目编辑工具可以使用NetBeans,可视化数据库管理软件使用Navicat,接口测试工具使用Postman;
  3. 接口项目使用面向对象的思想实现,将不同资源的业务封装到对应的资源类进行管理,提取公用的函数放入工具类,将错误码集成到错误码类进行统一配置;
  4. 可以自行建立基本的文件夹和文件,也可以导入模板后进行修改,模板文件和项目文件下面的附录可见;
  5. 使用Postman对项目接口进行统一管理,便于相关功能的测试;
  6. 进行接口测试时,如果需要修改数据库中的数据,尽量通过相关的信息修改接口进行调整,不要直接在Navicat中进行修改,避免破坏数据表的数据完整性;

5. 附录

5.1 SQL学习链接

  1. 学习视频:https://www.bilibili.com/video/BV1Vt411z7wy
  2. 博客链接:https://blog.csdn.net/m0_50546016/article/details/120070003

5.2 PHP学习链接

  1. PHP菜鸟教程:https://www.runoob.com/php/php-tutorial.html
  2. 学习视频:https://www.bilibili.com/video/BV18x411H7qD

5.3 HTTP相关链接

  1. 相关博客:https://blog.csdn.net/weixin_45803426/article/details/116784443

5.4 项目模板链接

  1. 项目模板:https://gitee.com/icebear221/php-interface-development.git
  2. 项目模板:https://download.csdn.net/download/ice_bear221/85690606

5.5 完整项目链接

  1. 便签接口:https://gitee.com/icebear221/php-interface-development.git
  2. 便签接口:https://download.csdn.net/download/ice_bear221/85690547

5.6 接口开发学习链接

  1. 学习视频:https://www.bilibili.com/video/BV1kW411P7A9?p=8

你可能感兴趣的:(后端接口,php,php,postman,mysql)