ThinkPHP5.0
文档
目录结构
TP5 在 web server
目录public下cmd
URL路径格式
域名及虚拟域名路径格式
路由 Route
application/route.php 路由配置文件
<?php
use think\Route;
// 注册路由到study模块的study控制器的show操作
Route::rule('studyShow','study/study/show');
;
多级控制器 (如在controller目录再新建了a,b,c目录)
// 注册路由到api模块的v1控制器下的Banner目录下的getBanner操作
Route::get('banner/:id','api/v1.Banner/getBanner');
获取路由参数
- 方式一
public function route($id,$name)
{
echo $id;
echo $name;
}
- 方式二
public function route()
{
$all = input('param.');
echo "获取所有<br/>";
var_dump($all);
echo "<br/>获取get所有<br/>";
$all = input('get.');
var_dump($all);
echo "<br/>获取指定get参数<br/>";
$all = input('get.name');
var_dump($all);
}
- 方式三
use think\Request;
public function route1(Request $Request)
{
$all = $Request->param();
echo "获取所有<br/>";
var_dump($all);
echo "<br/>获取get所有<br/>";
$all = $Request->get();
var_dump($all);
echo "<br/>获取指定get参数<br/>";
$all = $Request->get('age');
var_dump($all);
}
Validate:独立验证
- 内置验证规则(补地址)
namespace app\api\controller\v1;
//引用Validate
use think\Validate;
class Banner
{
public function getBanner()
{
// 虚拟数据
$data = [
'name' => '张三',
'email' => '25767@qq.com'
];
//配置规则
$validate = new Validate([
// 不能为空|最大程度3
'name' => 'require|max:3',
// 必须是email格式
'email' => 'email'
]);
$result = $validate->batch()->check($data);
//验证通过返回true 否则false
var_dump($result);
//返回错误信息array
var_dump($validate -> getError());
}
}
Validate:验证器(封装性更好)
- 创建验证器
- 使用
//引入
use app\api\controller\validate\MyValidate;
class Banner
{
public function getBanner()
{
// 虚拟数据
$data = [
'name' => '张三1111',
'email' => '25767@qq.comasdas'
];
$validate = new MyValidate();
$result = $validate->batch()->check($data);
var_dump($validate -> getError());
}
}
Validate:自定义验证规则
- 新建验证器
app\api\controller\validate\IDMustBePostivelnt
<?php
namespace app\api\controller\validate;
use think\Validate;
class IDMustBePostivelnt extends Validate
{
protected $rule = [
//不能为空|自定义规则
'id' => 'require|isId'
];
protected function isID($value,$rule = '' ,$data = '',$field = '')
{
//必须为数字必须为整型必须对于0
if (is_numeric($value) && is_int($value + 0) && ($value + 0 ) > 0) {
return true;
} else {
return $field.'必须是整数';
}
}
}
- 使用验证器
use app\api\controller\validate\IDMustBePostivelnt;
public function validate($id)
{
$data = [
'id' => $id
];
$validate = new IDMustBePostivelnt();
$result = $validate -> batch() -> check($data);
var_dump($validate -> getError());
}
构造接口函数校验层
-
路由
Route::get('banner/:id','api/v1.Banner/getBanner');
-
BaseValidate
<?php
namespace app\api\controller\validate;
use think\image\Exception;
use think\Validate;
class BaseValidate extends Validate
{
public function goCheck()
{
$allData = input('param.');
$result = $this -> check($allData) ;
if (!$result) {
$error = $this -> error;
//TP5异常抛出
throw new Exception($error);
} else {
return true;
}
}
}
- IDMustBePostivelnt
<?php
namespace app\api\controller\validate;
use think\Validate;
class IDMustBePostivelnt extends BaseValidate
{
protected $rule = [
'id' => 'require|isId'
];
protected function isID($value,$rule = '' ,$data = '',$field = '')
{
if (is_numeric($value) && is_int($value + 0) && ($value + 0 ) > 0) {
return true;
} else {
return $field.'必须是整数';
}
}
}
- Banner
<?php
namespace app\api\controller\v1;
use app\api\controller\validate\IDMustBePostivelnt;
class Banner
{
public function getBanner()
{
(new IDMustBePostivelnt()) -> goCheck();
}
}
自定义全局处理异常
- 定义基本错误异常
<?php
namespace app\lib\exception;
//基本异常
use think\Exception;
class BaseException extends Exception //!!! 必须继承Exception
{
public $code = 400;
public $message = '参数错误QAQ';
public $errorCode = 10000;
}
- 再定义一个如果数据不存在的异常
BannerMissException
<?php
namespace app\lib\exception;
class BannerMissException extends BaseException //!!! 继承上面的基本异常
{
public $code = 404;
public $message = '您请求的Banner不存在QAQ';
public $errorCode = 40000;
}
- 定义自己的Handler
<?php
namespace app\lib\exception;
//ExceptionHandler
use Exception;
use think\exception\Handle;
use think\Log;
use think\Request;
class ExceptionHandler extends Handle
{
private $code;
private $message;
private $errorCode;
public function render(Exception $e)
{
// 如果是自定义的异常
if ($e instanceof BaseException){
$this -> code = $e->code;
$this -> message = $e -> message;
$this -> errorCode = $e -> errorCode;
} else {
$this -> code = 500;
$this -> message = 'QAQ服务器内部错误,请稍后重试!';
}
$request = Request::instance();
$result = [
'message' => $this -> message,
'error_code' => $this -> errorCode,
//请求路径
'request_url' => $request->url(),
];
//返回给前台
return json($result,$this -> code);
}
}
- 开始使用自定义的异常处理
//模拟数据 假设查不到Banner
$banner = false;
if (!$banner) {
// 抛出上面定义的第二个异常
//!!! 这里需要修改config里的exception_handle配置项(如图)
throw new BannerMissException();
}
return $banner;
- 响应
基于自定义全局处理异常加入错误记录
- 首先
- 修改自己定义的Handler类
ExceptionHandler
<?php
namespace app\lib\exception;
//ExceptionHandler
use Exception;
use think\exception\Handle;
use think\Log;
use think\Request;
class ExceptionHandler extends Handle
{
private $code;
private $message;
private $errorCode;
public function render(Exception $e)
{
// 如果是自定义的异常
if ($e instanceof BaseException){
$this -> code = $e->code;
$this -> message = $e -> message;
$this -> errorCode = $e -> errorCode;
} else {
$this -> code = 500;
$this -> message = 'QAQ服务器内部错误,请稍后重试!';
$this -> errorCode = 999;
// 记录日志 ------------------修改了这里--------------------------
$this -> recordErrorLog($e);
// 记录日志 ------------------修改了这里--------------------------
}
$request = Request::instance();
$result = [
'message' => $this -> message,
'error_code' => $this -> errorCode,
//请求路径
'request_url' => $request->url(),
];
return json($result,$this -> code);
}
// ------------------添加了方法--------------------------
private function recordErrorLog(Exception $e)
{
// 初始化日志记录
Log::init([
'type' => 'File', //记录到文件中
'path' => LOG_PATH, //路径
'level' => ['error'] //自定义级别(这里为error级别)
]);
// 开始记录
Log::record(
$e->getMessage(), //记录的信息
'error'//级别
);
}
}
- 使用
$banner = false;
if (!$banner) {
// 抛出错误
throw new Exception('模拟服务器内部错误');
}
- 响应
- 查看runtime目录下的日志
---------------------------------------------------------------
[ 2020-03-26T17:35:01+08:00 ] 127.0.0.1 GET www.wx.com/banner/123
[ error ] [0]模拟服务器错误
[ error ] 模拟服务器错误
Handel:全局处理异常应用
- 1.开发环境与生存环境时的异常显示
- 开发环境时应返回错误信息html页面
- 生存环境时引返回JSON格式的错误信息
在自上面定义的Handel类中添加
- 当config中app_debug为true时
当config中app_debug为false时
Handel:优化自定义全局处理异常
BaseException
<?php
namespace app\lib\exception;
use think\Exception;
use Throwable;
class BaseException extends Exception
{
public $code = 400;
public $msg = '参数错误QAQ'; //这里将原本的$message变量名改成了$msg 不然好像有点小问题
public $errorCode = 10000;
public function __construct($param = [])
{
if (!is_array($param)) {
// 如果传过来的不是一个数组
return;
}
if (array_key_exists('code',$param)) {
// 如果数组中有code
$this -> code = $param['code'];
}
if (array_key_exists('msg',$param)) {
$this -> msg = $param['msg'];
}
if (array_key_exists('errorCode',$param)) {
$this -> errorCode = $param['errorCode'];
}
//这样code`msg`errorCode就可以在new的时候直接传入
}
}
- 使用
//模拟验证器 有时会有多个错误提示信息
$error = [
'name' => '姓名不能为空',
'age' => '年龄必须大于0'
]
$e = new ParameterException([
'msg' => $this -> error
]);
throw $e;
数据库操作 Db
- 连接数据库 database.php 配置文件
查
// 返回满足条件的第一条数据
$data1 = Db::table('banner_item') -> where('type','=',1) -> find();
// 返回二维数组 满足条件的多条数据
$data2 = Db::table('banner_item') -> where('type','=',1) -> select();
return json($data1);
增
$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::table('think_user')->insert($data);
删
// 根据主键删除
Db::table('think_user')->delete(1);
Db::table('think_user')->delete([1,2,3]);
// 条件删除
Db::table('think_user')->where('id',1)->delete();
Db::table('think_user')->where('id','<',10)->delete();
改
Db::table('think_user')->where('id', 1)->update(['name' => 'thinkphp']);
关于数据查询日志记录
-
默认是开启的(如果改变了默认的日志记录)
在index.php 入口文件中
<?php
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
\think\Log::init([
'type' => 'File',
'path' => LOG_PATH,
'level' => ['sql']
]);
模型
-
继承模型
-
创建模型的命名
php think make:model
-
实践
- 执行命令
查
//select可以传数组匹配多个id 返回数组
$idss = explode(',',$ids);
$data = ThemeModel::with('topIcImg,headImg') -> select($idss);
// find查询单个
$data = ThemeModel::finde($id)
//查询指定条数并排序
$data = ThemeModel::limit($count) -> order('create_time desc') -> select(
);
关于数据集返回类型
- database配置文件中
// 数据集返回类型 默认为array数组
'resultset_type' => 'array',
// 返回类型为数据集
'resultset_type' => 'collection',
-
当返回为array数组时当数据查询为空时返回null
-
当返回为数据集时当数据查询为空时返回一个空数组
-
如何判断是否查询失败?
-
//$data为 数据集 $data = ThemeModel::with('topIcImg,headImg') -> select($idss); // 判断是否为空 if ($data -> isEmpty()) { throw new ThemeException(); }
-
-
当返回为数据集时可以实现此处查询隐藏数据库摸个字段(场景:跟update_time不同有些字段有时候不需要隐藏有时候需要)
-
//$data为 collectionn数据集 $data = self::limit($count) -> order('create_time desc') -> select(); //隐藏summary字段 $data = $data -> hidden(['summary']); return $data;
-
-
关于返回类型是数据集转数组
配置文件 database.php
// 数据集返回类型
'resultset_type' => 'collection',
// 自动写入时间戳字段
'auto_timestamp' => 'datetime',
// 时间字段取出后的默认时间格式
然后在查询的最后加上toArray();
$user = UserModel::where('phone',$postData['phone']) -> where('password',md5($postData['pas'])) -> select() -> toArray();
var_dump($user);
模型-关联查询
hasMany
- 定义
- 使用
// items为什么模型中定义的方法名
$data = BannerM::with(['items']) -> find($id);
rreturn $data;
-
belongsToMany
多对多 -
belongs
一对一 -
使用
$data = BannerM::with(['items','items.img']) -> find($id);
return $data;
定义自己的配置文件
-
thinkPHP5 会自动获取指定目录下的配置文件
application/extra
-
在extra目录下新建php文件
myConfig.php
<?php
return [
'img_url' => 'http://www.wx.com/images'
];
- 获取配置项值
$url = config('myConfig.img_url');
模型-读取器
- 简单使用
- 在模型中定义方法
-
结果
- 原本数据
- 读取器执行后
微信小程序Token验证
- 操作器
/**
* @url api/v1/token/user?code=001Wcpg20sjimK1fLgg20CTpg20WcpgL
*/
public function getToken($code = '')
{
(new UserTokenValidate()) -> goCheck();
$ut = new UserToken($code);
$token = $ut->get();
return json([
'Token' => $token,
]);
}
- 新建
- UserToken.php
- 获取微信信息
protected $code;
protected $wxAppID;
protected $wxAppSecret;
protected $wxLoginUrl;
public function __construct($code)
{
$this->code=$code;
$this->wxAppID=config('WX.app_id');
$this->wxAppSecret=config('WX.app_secret');
$this->wxLoginUrl=sprintf(config('WX.login_url'),$this->wxAppID,$this->wxAppSecret,$this->code);
}
- wx配置文件
- UserToken -> get
public function get()
{
// 发现get请求拿到小程序api返回的数据
$result = curl_get($this -> wxLoginUrl);
// 转数组
$wxResult = json_decode($result,true);
if (empty($wxResult)) {
throw new Exception('获取session_key及openID时异常,微信内部错误');
} else {
// 如果拿到了判断有没有错误信息
$loginFail = array_key_exists('errcode',$wxResult);
// 如果有错误信息
if ($loginFail) {
// 抛出异常
$this -> processLoginError($wxResult);
} else {
// 去拿Token
return $this -> grantToken($wxResult);
}
}
}
- 抛出异常处理
processLoginError
private function processLoginError($wxResult)
{
throw new WeChatException([
'msg' => $wxResult['errmsg'],
'errorCode' => $wxResult['errcode'],
]);
}
- WeChatException
class WeChatException extends BaseException
{
public $code = 400;
public $msg = '微信服务器接口调用失败';
public $errorCode = 999;
}
- 拿Token
UserToken ->grantToken
private function grantToken($wxRwsult)
{
// 拿到openid
// 数据库看一下,这个openid是不是已存在
// 如果存在。,则不处理,如果不存在那么就新增一条user记录
// 生成令牌,准备存储数据,写入数据
// 把令牌返回到客户端去
$openid = $wxRwsult['openid'];
$user = User::getUserOpenid($openid);
if ($user) {
// 如果查询到了
$uid = $user -> id;
} else {
$uid = $this->newUser($openid);
}
// 整理缓存数据
$cachedValue = $this->prepareCachedValue($wxRwsult,$uid);
// 开始存入缓存并拿到token
$token = $this -> saveToCanche($cachedValue);
return $token;
}
- 写入数据 newUser
private function newUser($openid)
{
// 模型新增数据
$user = User::create([
'openid' => $openid,
]);
return $user->id;
}
- 整理缓存数据
prepareCachedValue
private function prepareCachedValue($wxRwsult,$uid)
{
$cachedValue = $wxRwsult;
$cachedValue['uid'] = $uid;
$cachedValue['scope'] = 16;
return $cachedValue;
}
- 开始存入缓存并拿到token
saveToCanche
private function saveToCanche($cachedValue)
{
//拿到一组加密Token
$key = self::generateToken();
$value = json_encode($cachedValue);
$expire_in = config('myConfig.token_expire_in');
// 开始存入缓存
$request = cache($key,$value,$expire_in);
if (!$request) {
throw new TokenException([
'msg' => '服务器缓存错误',
'errorCode' => 10005
]);
}
// 返回令牌
return $key;
}
- 拿到一组加密Token
generateToken
class Token
{
public static function generateToken()
{
// 32为的随机字符串 getRandChar在common中
$randChars = getRandChar(32);
// 访问时的时间戳
$timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
// salt 盐
$token_salt = config('myConfig.token_salt');
// 用三组数据进行md5加密返回
return md5($randChars.$timestamp.$token_salt);
}
}
- TP5 默认存储文件
- 测试
Token 应用
- 使用token认证 (场景:用户修改个人信息)
- 其中 AddressNew Validate 校验
- 其中的isNoteEmpty|isMobile 自定义规则 继承的BaseValidate
- 其中的
getCurrentUid
方法
- 其中的
getDataByRule
方法
模型-关联查询中进行排序
- 闭包函数构造查询器
TP5 方法前置
- !!! 必须继承Controller