# 1.安装tp6
composer create-project topthink/think mv
#2 创建User控制器
php think make:controller User --api
#3 创建User模型,对应数据库表 user
php think make:model User
用phpmyadmin创建数据库,并在.env文件中填写数据库信息;user表字段为:
然后编辑控制器 user.index 方法:
浏览器打开:正常显示;
然后再次编辑user.index.方法,这时我们显示点别的,就显示数据库user模型的内容;
#注意顶部引入User模型;as避免重名
use app\model\User as UserModel;
#重写index方法,select()选择数据库内所有行;
public function index()
{
return UserModel::select();
}
效果如下:
和数据库是对应的,如果有错误,把config/app.php的 'show_error_msg' => true打开,显示错误信息;example.env改成.env,然后配置数据库连接信息;
以下非常简单,有点tp基础的都可以弄;下面,继续;
api请求是json格式的,如何让请求的内容为json;如果为api快速创建路由:
1.资源路由;
编辑:route/app.php,增加一条资源 路由;
Route::resource('user', 'User');
然后可以用命令查看:
这样一来,直接编辑User控制器的方法就行了;资源路由己经默认创建了一些方法; 我们编辑这些方法让其返回json数据,核心代码就是:
return \think\Response::create($result, $type);
说白了,就是用tp的Response对象的create建立一个响应,类型为json,好,下面来封装这个方法,让他好看点;
在app\controller控制器目录下建立 Base.php,这个是虚基类,让其它控制器继承:
修改User控制器:
public function index()
{
$data = \app\model\User::field('id,username,email')->select();
//查询所有数据
return $this->create($data, $data->isEmpty() ? '数据不存在' : '数据请求成功');
}
显示结果就是json数据了:
下面,来个分页:也是编辑user.index控制器方法:
public function index()
{
$data = \app\model\User::field('id,username,email')->paginate(5);
return $this->create($data, $data->isEmpty() ? '数据不存在' : '数据请求成功');
}
第二页:注意url参数:
完善User.read控制器方法,使其能访问/user/2 (访问id为2的用户信息)
public function read($id)
{
//
//判断$id 为整型
if (!Validate::isInteger($id)) {
return $this->create([], 'id 参数错误~', 400);
}
//获取数据
$data = UserModel::field('id,username,email')->find($id);
//查询数据
if (empty($data)) {
return $this->create([], '没有数据', 204);
} else {
return $this->create($data, '数据请求成功', 200);
}
}
其它的save,delete,就不写了,自己完善,这时,请求api,以json返回就可以了;现在,我们来做token验证;
1.安装 jwt;
composer require firebase/php-jwt
创建一个token服务 ,会在app/service目录下生成Token.php,然后修改Token.php文件,这个文件基本上就是生成token字符串,校验的作用;自己手工创建也是一样的;
然后,我们创建一个中间件,用于检测token,如果没有token,就给客户端(前端)返回错误,提示没有登录 什么的。。。
JWT生成和效验common.php公共函数:
<?php
use \Firebase\JWT\JWT;
use Firebase\JWT\Key;
// 应用公共文件
/**
* 生成验签
* @param $uid 用户id
* @return mixed
*/
function signToken($uid){
$key='abcdefg'; //自定义的一个随机字串用户于加密中常用的 盐 salt
$token=array(
"iss"=>$key, //签发者 可以为空
"aud"=>'', //面象的用户,可以为空
"iat"=>time(), //签发时间
"nbf"=>time()+2, //在什么时候jwt开始生效
"exp"=> time()+7200, //token 过期时间
"data"=>[ //记录的uid的信息
'uid'=>$uid,
]
);
// print_r($token);
$jwt = JWT::encode($token, $key, "HS256"); //生成了 token
return $jwt;
}
/**
* 验证token
* @param $token
* @return array|int[]
*/
function checkToken($token){
$key='abcdefg'; //自定义的一个随机字串用户于加密中常用的 盐 salt
$res['status'] = false;
try {
JWT::$leeway = 60;//当前时间减去60,把时间留点余地
$decoded = JWT::decode($token, new Key($key, 'HS256')); //HS256方式,这里要和签发的时候对应
$arr = (array)$decoded;
$res['status'] = 200;
$res['data'] =(array)$arr['data'];
return $res;
} catch(\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
$res['info'] = "签名不正确";
return $res;
}catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
$res['info'] = "token失效";
return $res;
}catch(\Firebase\JWT\ExpiredException $e) { // token过期
$res['info'] = "token失效";
return $res;
}catch(Exception $e) { //其他错误
$res['info'] = "未知错误";
return $res;
}
}
php think make:middleware Auth
这条命令会在app\middleware下创建Auth.php中间件,中间件有全局,控制器,路由三种,这里我们用路由中间件;
我们修改这个中间件(Auth.php):
public function handle($request, \Closure $next)
{
//
//第一步先取token
$token = $request->header('token');
//jwt进行校验token
$res = (new TokenServer())->chekToken($token);
if ($res['code'] != 1 ){
return ['error_code'=>999,'msg'=>$res['msg'],'data'=>''];
}
$request->uid = $res['data']->uid;
return $next($request);
}
这个中间件的作用是:从请求头中读取token,然后调用TokenServer类的checkToken()方法来检测这个token是否正确,如果正确,就什么都不干,直接把请求加上一个uid后,直接next,这个next,就是下一步,假设请求路由是 http://localhost/index.php/user/2,token也正确,这时他会直接返回请求内容,中间件就像不存在一样,但是,一但客户没有token(未登录),或是token错误(过期),这时,他就不会返回请求内容,而是 return [ error_code 999 当然,这里也可以转向到Login登录页;提示前端登录 ,访问了需要授权登录 的页面;
注意:上面的:要注意,中间件可能在实际中是验证缓存中的token.只有登录才是验证header.或表单;