什么是数据库三大范式javascript
数据库中设计中的常见问题php
一对一 (学生姓名, 学号)
一对多 (老师, 学生)
多对多 (学生, 课程)html
设计数据库的小技巧java
数据库名
作前缀表名
作前缀缩写
基本语法sql
用户登陆
举例thinkphp
post
www.test.com/apiapi.test.com
数据库
参数 | 必选 | 类型 | 说明 |
---|---|---|---|
time | true | int | 时间戳 (用于肯定接口的访问时间) |
token | true | string | 肯定访问者身份 (MD5(USER_MD5(time)_USER) ) |
username | true | string | 只接受手机号 |
password | true | string | 用户密码 |
{ "ret": 200, // 返回结果状态。200:接口正常请求并返回/40*:服务端的数据有误/500:服务器运行错误 "data": { "user_id": "27", // 用户id "user_tag": "1" // 用户身份 }, "msg": "" // 401:用户名不存在!/402:手机号不存在!/403:密码不正确! }
api.tp5.com/user/2
===> www.tp5.com/index.php/api/user/index/id/2
其余选项菜单
==> 站点域名管理
网站域名:
www.tp5.com
网站域名:G:\phpStudy\WWW\tp5\public
第二域名:api.tp5.com
网站端口:80
json
127.0.0.1 www.tp5.com 127.0.0.1 api.tp5.com
package control: install package
SideBarEnhancementsapi
路径:
G:\phpStudy\WWW\tp5\application\config.php
跨域// 是否开启路由 'url_route_on' => true, // 域名部署 'url_domain_deploy' => true,
D:\phpStudy\WWW\tp5\application\route.php
<?php use think\Route; Route::domain('api', 'api'); Route::get('user', 'user/index');新建
api/controller/User.php
<?php namespace app\api\controller; class User { public function index() { echo 'user/index'; echo '<br>'; $id = input('id'); echo $id; echo '<br>'; $name = input('name'); print_r($name); } }访问下面地址均可以打开:
http://api.tp5.com/user/index?id=1&name=lisi
http://api.tp5.com/user?id=1&name=lisi
http://api.tp5.com/user/id/1/name/lisi
http://www.tp5.com/api/user/index?id=1&name=lisi
http://www.tp5.com/api/user/index/id/1/name/lisi
输出:user/index 1 lisi下面这些访问拿不到参数
http://api.tp5.com/user/index/id/1/name/lisi
输出:user/index
D:\phpStudy\WWW\tp5\application\route.php
<?php use think\Route; Route::domain('api', 'api'); Route::get('user/:id/:name', 'user/index');
新建 api/controller/User.php
<?php namespace app\api\controller; class User { public function index() { echo 'user/index'; echo '<br>'; $id = input('id'); echo $id; echo '<br>'; $name = input('name'); print_r($name); } }下面这些访问拿不到参数
http://api.tp5.com/user/1/lisi
http://api.tp5.com/user?id=1&name=lisi
http://www.tp5.com/api/user/index?id=1&name=lisi
http://www.tp5.com/api/user?id=1&name=lisi
http://www.tp5.com/api/user/index/id/1/name/lisi
输出:user/index 1 lisi*下面这种会报错 *
http://api.tp5.com/user/index?id=1&name=lisi
非法请求:api/user/index
常见的安全问题以及解决方案
解决方案: 获取 timestamp (时间戳), 设置接口失效时间
解决方案: 对参数加密, 生成 token , 判断 token 是否正确
解决方案: 使用 https , 用证书对数据进行加密, 即便数据被截取, 对黑客也没有意义
黑客能够获取数据, 可是没法获取数据的加密方法
咱们api项目的安全设计
时间戳, 用于判断请求是否超时, 设置为30秒
其余参数加密而来, 保证数据不被篡改
接收加密过的用户密码, 用户密码永不返回
最好使用 https, 全部信息都会被加密
配置路由
G:\phpStudy\WWW\tp5\application\config.php
// 是否开启路由 'url_route_on' => true, // 域名部署 'url_domain_deploy' => true,
G:\phpStudy\WWW\tp5\application\route.php
<?php use think\Route; // api.tp5.com ===> www.tp5.com/index.php/api Route::domain('api','api'); // post api.tp5.com/user ---> user.php login() Route::post('user','user/login');
使用common.php
统一处理参数过滤
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
<?php namespace app\api\controller; use think\Controller; use think\Request; use think\Validate; class Common extends Controller { protected $request; // 用来处理参数 protected $validater; // 用来验证数据/参数 protected $params; // 过滤后符合要求的参数 protected $rules = array( 'User'=>array(......); protected function _initialize() { parent::_initialize(); $this->request = Request::instance(); $this->check_time($this->request->only(['time'])); $this->check_token($this->request->param()); $this->params = $this->check_params($this->request->except(['time','token'])); }
自定义返回信息函数
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
/** * api 数据返回 * @param [int] $code [结果码 200:正常/4**数据问题/5**服务器问题] * @param [string] $msg [接口要返回的提示信息] * @param [array] $data [接口要返回的数据] * @return [string] [最终的json数据] */ public function return_msg($code, $msg = '', $data = []) { /*********** 组合数据 ***********/ $return_data['code'] = $code; $return_data['msg'] = $msg; $return_data['data'] = $data; /*********** 返回信息并终止脚本 ***********/ echo json_encode($return_data);die; }
验证time
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
/** * 验证请求是否超时 * @param [array] $arr [包含时间戳的参数数组] * @return [json] [检测结果] */ public function check_time($arr) { //intval() string 11返回11 11hello返回11 hello返回0 array 空array返回0 非空array返回1 //intval($arr['time']) <= 1 等于1就是非空array(不是咱们想要的) //小于1即等于0就是string或者空array或者是空(也不是咱们想要的) //我想要想要的是一串数字,因此 intval($arr['time']) <= 1就报错 if (!isset($arr['time']) || intval($arr['time']) <= 1) { $this->return_msg(400, '时间戳不正确!'); } if (time() - intval($arr['time']) > 60) { $this->return_msg(400, '请求超时!'); } }
验证token
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
/** * 验证token(防止篡改数据) * @param [array] $arr [所有请求参数] * @return [json] [token验证结果] */ public function check_token($arr) { /*********** api传过来的token ***********/ if (!isset($arr['token']) || empty($arr['token'])) { $this->return_msg(400, 'token不能为空!'); } $app_token = $arr['token']; // api传过来的token /*********** 服务器端生成token ***********/ unset($arr['token']); $service_token = ''; foreach ($arr as $key => $value) { $service_token .= md5($value); } $service_token = md5('api_' . $service_token . '_api'); // 服务器端即时生成的token /*********** 对比token,返回结果 ***********/ if ($app_token !== $service_token) { $this->return_msg(400, 'token值不正确!'); } }
为每一个接口配置验证规则
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
protected $rules = array( 'User' => array( 'login' => array( 'user_name' => ['require', 'chsDash', 'max' => 20], 'user_pwd' => 'require|length:32', ), ), );
验证参数
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
/** * 验证参数 参数过滤 * @param [array] $arr [除time和token外的全部参数] * @return [return] [合格的参数数组] */ public function check_params($arr) { /*********** 获取参数的验证规则 ***********/ $rule = $this->rules[$this->request->controller()][$this->request->action()]; /*********** 验证参数并返回错误 ***********/ $this->validater = new Validate($rule); if (!$this->validater->check($arr)) { $this->return_msg(400, $this->validater->getError()); } /*********** 若是正常,经过验证 ***********/ return $arr; }
接口文档
新建api_user表
DROP TABLE IF EXISTS `api_user`; CREATE TABLE `api_user` ( `user_id` int(11) NOT NULL AUTO_INCREMENT, `user_phone` char(11) NOT NULL, `user_nickname` varchar(255) NOT NULL COMMENT '昵称', `user_email` varchar(255) NOT NULL, `user_rtime` int(11) NOT NULL COMMENT 'register time', `user_pwd` char(32) NOT NULL, `user_icon` varchar(255) NOT NULL COMMENT '用户头像', PRIMARY KEY (`user_id`) ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
验证码原理
- 点击获取手机码
- 发送手机号到后台
- 后台生成手机码
- 用session保存手机码及手机号
- 用短信发送平台的接口发送出去
- 获取用户输入的手机码及手机号
- 取出session保存的内容
- 对比验证
- 返回信息, 结束
配置路由
注意: get方式没有参数名, 因此要注意参数的顺序, 对号入座.
G:\phpStudy\WWW\tp5\application\route.php
// 获取验证码 Route::get('code/:time/:token/:username/:is_exist','code/get_code');
参数过滤
在common.php里简单过滤, 具体验证放在code.php里
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'Code' => array( 'get_code' => array( 'username' => 'require', 'is_exist' => 'require|number|length:1', ), ),
检测用户名
G:\phpStudy\WWW\tp5\application\api\controller\Code.php
namespace app\api\controller; use phpmailer\phpmailer; use submail\messagexsend; class Code extends Common { public function get_code() { $username = $this->params['username']; $exist = $this->params['is_exist']; $username_type = $this->check_username($username); // 检查用户名, 决定用下面哪那个函数 switch ($username_type) { case 'phone': $this->get_code_by_username($username, 'phone', $exist); // 经过手机获取验证码 break; case 'email': $this->get_code_by_username($username, 'email', $exist); // 经过邮箱获取验证码 break; } } }
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
public function check_username($username) { /*********** 判断是否为邮箱 ***********/ $is_email = Validate::is($username, 'email') ? 1 : 0; /*********** 判断是否为手机 ***********/ $is_phone = preg_match('/^1[34578]\d{9}$/', $username) ? 4 : 2; /*********** 最终结果 ***********/ $flag = $is_email + $is_phone; switch ($flag) { /*********** not phone not email ***********/ case 2: $this->return_msg(400, '邮箱或手机号不正确!'); break; /*********** is email not phone ***********/ case 3: return 'email'; break; /*********** is phone not email ***********/ case 4: return 'phone'; break; } }
经过用户名(手机/邮箱)获取验证码
G:\phpStudy\WWW\tp5\application\api\controller\Code.php
public function get_code_by_username($username, $type, $exist) { if ($type == 'phone') { $type_name = '手机'; } else { $type_name = '邮箱'; } /*********** 检测手机号/邮箱是否存在 ***********/ $this->check_exist($username, $type, $exist); /*********** 检查验证码请求频率 30秒一次 ***********/ if (session("?" . $username . '_last_send_time')) { if (time() - session($username . '_last_send_time') < 30) { $this->return_msg(400, $type_name . '验证码,每30秒只能发送一次!'); } } /*********** 生成验证码 ***********/ $code = $this->make_code(6); /*********** 使用session存储验证码, 方便比对, md5加密 ***********/ $md5_code = md5($username . '_' . md5($code)); session($username . '_code', $md5_code); /*********** 使用session存储验证码的发送时间 ***********/ session($username . '_last_send_time', time()); /*********** 发送验证码 ***********/ if ($type == 'phone') { $this->send_code_to_phone($username, $code); } else { $this->send_code_to_email($username, $code); } }
判断用户名(手机/邮箱)是否应该存在
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
public function check_exist($value, $type, $exist) { $type_num = $type == "phone" ? 2 : 4; $flag = $type_num + $exist; $phone_res = db('user')->where('user_phone', $value)->find(); $email_res = db('user')->where('user_email', $value)->find(); switch ($flag) { /*********** 2+0 phone need no exist ***********/ case 2: if ($phone_res) { $this->return_msg(400, '此手机号已被占用!'); } break; /*********** 2+1 phone need exist ***********/ case 3: if (!$phone_res) { $this->return_msg(400, '此手机号不存在!'); } break; /*********** 4+0 email need no exist ***********/ case 4: if ($email_res) { $this->return_msg(400, '此邮箱已被占用!'); } break; /*********** 4+1 email need exist ***********/ case 5: if (!$email_res) { $this->return_msg(400, '此邮箱不存在!'); } break; } }
生成验证码
G:\phpStudy\WWW\tp5\application\api\controller\Code.php
public function make_code($num) { $max = pow(10, $num) - 1; $min = pow(10, $num - 1); return rand($min, $max); }
经过邮箱发送验证码
去邮箱开启
smtp
php须要开启php_openssl
如今phpmailer并把须要的文件添加进thinkphp5
G:\phpStudy\WWW\tp5\extend\phpmailer\phpmailer.php
namespace phpmailer; use phpmailer\smtp; class PHPMailer ...... class phpmailerException extends \Exception...... // 须要加\
G:\phpStudy\WWW\tp5\extend\phpmailer\smtp.php
namespace phpmailer; class SMTP ......
G:\phpStudy\WWW\tp5\application\api\controller\Code.php
public function send_code_to_email($email, $code) { $toemail = $email; $mail = new PHPMailer(); $mail->isSMTP(); $mail->CharSet = 'utf8'; // 设置字符集 $mail->Host = 'smtp.126.com'; // smtp服务器 $mail->SMTPAuth = true; $mail->Username = "xujunhao_api@126.com"; $mail->Password = "xujunhao890518"; // 本身设置的smtp密码, 与登陆密码无关 $mail->SMTPSecure = 'ssl'; $mail->Port = 994; $mail->setFrom('xujunhao_api@126.com', '接口测试'); $mail->addAddress($toemail, 'test'); $mail->addReplyTo('xujunhao_api@126.com', 'Reply'); $mail->Subject = "您有新的验证码!"; // 邮件标题 $mail->Body = "这是一个测试邮件,您的验证码是$code,验证码的有效期为1分钟,本邮件请勿回复!"; // 邮件内容 if (!$mail->send()) { $this->return_msg(400, $mail->ErrorInfo); } else { $this->return_msg(200, '验证码已经发送成功,请注意查收!'); } }
经过手机发送验证码 使用submail(赛迪云通讯)
- 开启
php_curl
- 安装本地证书下载证书
G:\phpStudy\php\php-5.5.38\php.ini
[curl] ; A default value for the CURLOPT_CAINFO option. This is required to be an ; absolute path. curl.cainfo = "G:\phpStudy\php\php-5.5.38\cacert.pem"
G:\phpStudy\WWW\tp5\application\api\controller\Code.php
public function send_code_to_phone($phone, $code) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'https://api.mysubmail.com/message/xsend'); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_POST, 1); $data = [ 'appid' => '15180', 'to' => $phone, 'project' => '9CTTG2', 'vars' => '{"code":' . $code . ',"time":"60"}', 'signature'=>'76a9e82484c83345b7850395ceb818fb', ]; curl_setopt($curl, CURLOPT_POSTFIELDS, $data); $res = curl_exec($curl); curl_close($curl); $res = json_decode($res); if ($res->status != 'success') { $this->return_msg(400,$res->msg); }else{ $this->return_msg(200,'手机验证码已发送, 天天发送5次, 请在一分钟内验证!'); } dump($res->staus);die; }
- 下载sdk, 把须要的文件加入thinkphp5
G:\phpStudy\WWW\tp5\extend\submail\message.php
namespace submail; class message {......
G:\phpStudy\WWW\tp5\extend\submail\messagexsend.php
namespace submail; use submail\message; class MESSAGEXsend { protected $appid = ''; protected $appkey = ''; protected $sign_type = ''; protected $To = array(); protected $Addressbook = array(); protected $Project = ''; protected $Vars = array(); function __construct() { $this->appid = "15180"; $this->appkey = "76a9e82484c83345b7850395ceb818fb"; $this->sign_type = 'normal'; }
G:\phpStudy\WWW\tp5\application\api\controller\Code.php
public function send_code_to_phone($phone, $code) { $submail = new MESSAGEXsend(); $submail->SetTo($phone); $submail->SetProject('9CTTG2'); $submail->AddVar('code', $code); $submail->AddVar('time', 60); $xsend = $submail->xsend(); if ($xsend['status'] !== 'success') { $this->return_msg(400, $xsend['msg']); } else { $this->return_msg(200, '手机验证码已发送, 天天发送5次, 请在一分钟内验证!'); } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户注册 Route::post('user/register','user/register');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
protected $rules = array( 'User' => array( 'register' => array( 'user_name' => 'require', 'user_pwd' => 'require|length:32', 'code' => 'require|number|length:6', ), ), );
关闭数据库字段检查
G:\phpStudy\WWW\tp5\application\database.php
// 是否严格检查字段是否存在 'fields_strict' => false,
书写register函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function register() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检查验证码 ***********/ $this->check_code($data['user_name'], $data['code']); /*********** 检测用户名 ***********/ $user_name_type = $this->check_username($data['user_name']); switch ($user_name_type) { case 'phone': $this->check_exist($data['user_name'], 'phone', 0); $data['user_phone'] = $data['user_name']; break; case 'email': $this->check_exist($data['user_name'], 'email', 0); $data['user_email'] = $data['user_name']; break; } /*********** 将用户信息写入数据库 ***********/ unset($data['user_name']); $data['user_rtime'] = time(); // register time $res = db('user')->insert($data); if (!$res) { $this->retrun_msg(400, '用户注册失败!'); } else { $this->return_msg(200, '用户注册成功!'); } }
检查验证码
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
public function check_code($user_name, $code) { /*********** 检测是否超时 ***********/ $last_time = session($user_name . '_last_send_time'); if (time() - $last_time > 60) { $this->return_msg(400, '验证超时,请在一分钟内验证!'); } /*********** 检测验证码是否正确 ***********/ $md5_code = md5($user_name . '_' . md5($code)); if (session($user_name . "_code") !== $md5_code) { $this->return_msg(400, '验证码不正确!'); } /*********** 无论正确与否,每一个验证码只验证一次 ***********/ session($user_name . '_code', null); }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户登陆 Route::post('user/login','user/login');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
protected $rules = array( 'User' => array( 'login' => array( 'user_name' => 'require', 'user_pwd' => 'require|length:32', ), ), );
书写login函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function login() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检测用户名 ***********/ $user_name_type = $this->check_username($data['user_name']); switch ($user_name_type) { case 'phone': $this->check_exist($data['user_name'], 'phone', 1); $db_res = db('user') ->field('user_id,user_name,user_phone,user_email,user_rtime,user_pwd') ->where('user_phone', $data['user_name']) ->find(); break; case 'email': $this->check_exist($data['user_name'], 'email', 1); $db_res = db('user') ->field('user_id,user_name,user_phone,user_email,user_rtime,user_pwd') ->where('user_email', $data['user_name']) ->find(); break; } if ($db_res['user_pwd'] !== $data['user_pwd']) { $this->return_msg(400, '用户名或者密码不正确!'); } else { unset($db_res['user_pwd']); // 密码永不返回 $this->return_msg(200, '登陆成功!', $db_res); } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户上传你头像 Route::post('user/icon','user/upload_head_img');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
protected $rules = array( 'User' => array( 'upload_head_img' => array( 'user_id' => 'require|number', 'user_icon' => 'require|image|fileSize:2000000000|fileExt:jpg,png,bmp,jpeg', ), ), );
修改参数过滤
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
$this->params = $this->check_params($this->request->param(true));
编写upload_head_img函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function upload_head_img() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 上传文件,得到路径 ***********/ $head_img_path = $this->upload_file($data['user_icon'], 'head_img'); /*********** 存入数据库 ***********/ $res = db('user')->where('user_id', $data['user_id'])->setField('user_icon', $head_img_path); if ($res) { $this->return_msg(200, '头像上传成功!', $head_img_path); } else { $this->return_msg(400, '上传头像失败!'); } }
编写upload_file函数
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
public function upload_file($file, $type = '') { $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads'); if ($info) { $path = '/uploads/' . $info->getSaveName(); /*********** 裁剪图片 ***********/ if (!empty($type)) { $this->image_edit($path, $type); } return str_replace('\\', '/', $path); } else { $this->return_msg(400, $file->getError()); } }
编写image_edit函数
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
public function image_edit($path, $type) { $image = Image::open(ROOT_PATH . 'public' . $path); switch ($type) { case 'head_img': $image->thumb(200, 200, Image::THUMB_CENTER)->save(ROOT_PATH . 'public' . $path); break; } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户修改密码 Route::post('user/change_pwd','user/change_pwd');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
protected $rules = array( 'User' => array( 'change_pwd' => array( 'user_name' => 'require', 'user_ini_pwd' => 'require|length:32', 'user_pwd' => 'require|length:32', ), ), );
编写change_pwd函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function change_pwd() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检查用户名并取出数据库中的密码 ***********/ $user_name_type = $this->check_username($data['user_name']); switch ($user_name_type) { case 'phone': $this->check_exist($data['user_name'], 'phone', 1); $where['user_phone'] = $data['user_name']; break; case 'email': $this->check_exist($data['user_name'], 'email', 1); $where['user_email'] = $data['user_name']; break; } /*********** 判断原始密码是否正确 ***********/ $db_ini_pwd = db('user')->where($where)->value('user_pwd'); if ($db_ini_pwd !== $data['user_ini_pwd']) { $this->return_msg(400, '原密码错误!'); } /*********** 把新的密码存入数据库 ***********/ $res = db('user')->where($where)->setField('user_pwd', $data['user_pwd']); if ($res !== false) { $this->return_msg(200, '密码修改为功!'); } else { $this->return_msg(400, '密码修改失败!'); } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户找回密码 Route::post('user/find_pwd','user/find_pwd');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
protected $rules = array( 'User' => array( 'find_pwd' => array( 'user_name' => 'require', 'user_pwd' => 'require|length:32', 'code' => 'require|number|length:6', ), ), );
书写find_pwd函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function find_pwd() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检测验证码 ***********/ $this->check_code($data['user_name'], $data['code']); /*********** 检测用户名 ***********/ $user_name_type = $this->check_username($data['user_name']); switch ($user_name_type) { case 'phone': $this->check_exist($data['user_name'], 'phone', 1); $where['user_phone'] = $data['user_name']; break; case 'email': $this->check_exist($data['user_name'], 'email', 1); $where['user_email'] = $data['user_name']; break; } /*********** 修改数据库 ***********/ $res = db('user')->where($where)->setField('user_pwd', $data['user_pwd']); if ($res !== false) { $this->return_msg(200, '密码修改为功!'); } else { $this->return_msg(400, '密码修改失败!'); } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户绑定手机号 Route::post('user/bind_phone','user/bind_phone'); // 用户绑定邮箱 Route::post('user/bind_email','user/bind_email');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'bind_phone' => array( 'user_id' => 'require|number', 'phone' => ['require','regex'=>'/^1[34578]\d{9}$/'], 'code' => 'require|number|length:6', ), 'bind_email' => array( 'user_id' => 'require|number', 'email' => 'require|email', 'code' => 'require|number|length:6', ),
书写bind_phone函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function bind_phone() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检查验证码 ***********/ $this->check_code($data['phone'], $data['code']); /*********** 修改数据库 ***********/ $res = db('user')->where('user_id', $data['user_id'])->setField('user_phone', $data['phone']); if ($res !== false) { $this->return_msg(200, '手机号绑定成功!'); } else { $this->return_msg(400, '手机号绑定失败!'); } }
书写bind_email函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function bind_email() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检查验证码 ***********/ $this->check_code($data['email'], $data['code']); /*********** 修改数据库 ***********/ $res = db('user')->where('user_id', $data['user_id'])->setField('user_email', $data['email']); if ($res !== false) { $this->return_msg(200, '邮箱绑定成功!'); } else { $this->return_msg(400, '邮箱绑定失败!'); } }
两个接口合成一个
G:\phpStudy\WWW\tp5\application\route.php
// 用户绑定邮箱/手机 Route::post('user/bind_username','user/bind_username');
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'bind_username' => array( 'user_id' => 'require|number', 'user_name' => 'require', 'code' => 'require|number|length:6', ),
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function bind_username() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 检测验证码 ***********/ $this->check_code($data['user_name'], $data['code']); /*********** 判断用户名 ***********/ $user_name_type = $this->check_username($data['user_name']); switch ($user_name_type) { case 'phone': $type_text = '手机号'; $update_data['user_phone'] = $data['user_name']; break; case 'email': $type_text = '邮箱'; $update_data['user_email'] = $data['user_name']; break; } /*********** 修改数据库 ***********/ $res = db('user')->where('user_id', $data['user_id'])->update($update_data); if ($res !== false) { $this->return_msg(200, $type_text . '绑定成功!'); } else { $this->return_msg(400, $type_text . '绑定失败!'); } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 用户修改昵称 Route::post('user/nickname','user/set_nickname');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'set_nickname' => array( 'user_id' => 'require|number', 'user_nickname' => 'require|chsDash', ),
编写set_nickname函数
G:\phpStudy\WWW\tp5\application\api\controller\User.php
public function set_nickname(){ /*********** 接收参数 ***********/ $data = $this->params; /*********** 检测昵称 ***********/ $res = db('user')->where('user_nickname',$data['user_nickname'])->find(); if ($res) { $this->return_msg(400,'该昵称已被占用!'); } /*********** 写入数据库 ***********/ $res = db('user')->where('user_id',$data['user_id'])->setField('user_nickname',$data['user_nickname']); if (!$res) { $this->return_msg(400,'修改昵称失败!'); }else{ $this->return_msg(200,'昵称修改为功!'); } }
接口文档
新建api_article表
DROP TABLE IF EXISTS `api_article`; CREATE TABLE `api_article` ( `article_id` int(11) NOT NULL AUTO_INCREMENT, `article_title` varchar(255) NOT NULL, `article_uid` int(11) NOT NULL COMMENT 'user id', `article_content` text NOT NULL, `article_ctime` int(11) NOT NULL, PRIMARY KEY (`article_id`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 新增文章 Route::post('article','article/add_article');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'Article' => array( 'add_article' => array( 'article_uid' => 'require|number', 'article_title' => 'require|chsDash', ), ),
编写add_article函数
G:\phpStudy\WWW\tp5\application\api\controller\Article.php
<?php namespace app\api\controller; class Article extends Common { public function add_article() { /*********** 接收参数 ***********/ $data = $this->params; $data['article_ctime'] = time(); /*********** 写入数据库 ***********/ $res = db('article')->insertGetId($data); if ($res) { $this->return_msg(200, '新增文章成功!',$res); } else { $this->return_msg(400, '新增文章失败!'); } } }
参数安全html代码实体化
防止跨域脚本攻击
G:\phpStudy\WWW\tp5\application\config.php
// 默认全局过滤方法 用逗号分隔多个 'default_filter' => 'htmlspecialchars',
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 查看文章列表 Route::get('articles/:time/:token/:user_id/[:num]/[:page]','article/article_list');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'Article' => array( 'article_list' => array( 'user_id' => 'require|number', 'num' => 'number', 'page' => 'number', ), ),
编写article_list函数
G:\phpStudy\WWW\tp5\application\api\controller\Article.php
<?php namespace app\api\controller; class Article extends Common { public function article_list() { /*********** 接收参数 ***********/ $data = $this->params; if (!isset($data['num'])) { $data['num'] = 10; } if (!isset($data['page'])) { $data['page'] = 1; } /*********** 查询数据库 ***********/ $where['article_uid'] = $data['user_id']; $where['article_isdel'] = 0; $count = db('article')->where($where)->count(); $page_num = ceil($count / $data['num']); $field = "article_id,article_ctime,article_title,user_nickname"; $join = [['api_user u', 'u.user_id = a.article_uid']]; $res = db('article')->alias('a')->field($field)->join($join)->where($where)->page($data['page'], $data['num'])->select(); /*********** 判断并输出 ***********/ if ($res === false) { $this->return_msg(400, '查询失败!'); } elseif (empty($res)) { $this->return_msg(200, '暂无数据!'); } else { $return_data['articles'] = $res; $return_data['page_num'] = $page_num; $this->return_msg(200, '查询成功!', $return_data); } } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 获取单个文章信息 Route::get('article/:time/:token/:article_id','article/article_detail');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'Article' => array( 'article_detail' => array( 'article_id' => 'require|number', ), ),
编写article_detail函数
G:\phpStudy\WWW\tp5\application\api\controller\Article.php
<?php namespace app\api\controller; class Article extends Common { public function article_detail() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 查询数据库 ***********/ $field = 'article_id,article_title,article_ctime,article_content,user_nickname'; $where['article_id'] = $data['article_id']; $join = [['api_user u', 'u.user_id = a.article_uid']]; $res = db('article')->alias('a')->join($join)->field($field)->where($where)->find(); $res['article_content'] = htmlspecialchars_decode($res['article_content']); /*********** 判断结果并输出 ***********/ if (!$res) { $this->return_msg(400, '查询失败!'); } else { $this->return_msg(200, '查询成功!', $res); } } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 修改/更新文章 Route::put('article','article/update_article');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'Article' => array( 'update_article' => array( 'article_id' => 'require|number', 'article_title'=>'chsDash' ), ),
编写update_article函数
G:\phpStudy\WWW\tp5\application\api\controller\Article.php
<?php namespace app\api\controller; class Article extends Common { public function update_article() { /*********** 接收参数 ***********/ $data = $this->params; /*********** 存入数据库 ***********/ $res = db('article')->where('article_id', $data['article_id'])->update($data); if ($res !== false) { $this->return_msg(200, '修改文章成功!'); } else { $this->return_msg(400, '修改文章失败!'); } } }
接口文档
配置路由
G:\phpStudy\WWW\tp5\application\route.php
// 删除文章 Route::delete('article/:time/:token/:article_id','article/del_article');
验证数据
G:\phpStudy\WWW\tp5\application\api\controller\Common.php
'Article' => array( 'del_article' => array( 'article_id' => 'require|number', ), ),
为逻辑删除增长字段article_isdel
DROP TABLE IF EXISTS `api_article`; CREATE TABLE `api_article` ( `article_id` int(11) NOT NULL AUTO_INCREMENT, `article_title` varchar(255) NOT NULL, `article_uid` int(11) NOT NULL COMMENT 'user id', `article_content` text NOT NULL, `article_ctime` int(11) NOT NULL, `article_isdel` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 1:yes 0:no', PRIMARY KEY (`article_id`) ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
编写del_article函数
G:\phpStudy\WWW\tp5\application\api\controller\Article.php
<?php namespace app\api\controller; class Article extends Common { public function del_article(){ /*********** 接收参数 ***********/ $data = $this->params; /*********** 删除数据(逻辑删除) ***********/ $res = db('article')->where('article_id',$data['article_id'])->setField('article_isdel',1); /*********** 删除数据(物理删除) ***********/ // $res = db('article')->delete($data['article_id']); if ($res) { $this->return_msg(200,'删除文章成功'); }else{ $this->return_msg(400,'删除文章失败!'); } } }