官方文档
由此开始:https://www.kancloud.cn/manual/thinkphp6_0/1037479
目录结构:https://www.kancloud.cn/manual/thinkphp6_0/1037483
伪静态设置:https://www.kancloud.cn/manual/thinkphp6_0/1037488
Thinkphp网址导航:http://sites.thinkphp.cn/1556332
1.安装lnmp之后做些什么?
open_basedir = /:/tmp/:/proc/,调整PHP目录访问权限;
display_errors = On,打开默认不显示的错误提示;
安装Redis,安装Swoole;
2.安装Thinkphp之后要做些什么?
安装think-view模板库: "topthink/think-view":"*";
Nginx解析的根目录改为Thinkphp项目所在的public目录;
Thinkphp伪静态修改好,并重启Nginx;
将runtime、session等需要写入的目录给予可写的权限;
启用Thinkphp的session:app/middleware.php写入;
代码语言:javascript复制thinkmiddlewareSessionInit::class
config/session.php调整session的有效期;
config/middleware.php新增中间件类的别名
代码语言:javascript复制'alias' => [
"Token"=>appmiddlewareToken::class,
"BusinessToken"=>appmiddlewareBusinessToken::class
],
config/database.php,修改数据库相关的配置信息;
config/filesystem.php,修改自带的文件管理库相关配置;
config/app.php ,修改应用相关配置(是否显示错误信息等等);
config/cache.php,配置redis等缓存数据库;
.env,修改调试的相关配置信息;
app/ExceptionHandle.php,修改默认错误信息输出的默认模板;
细节总结
1.基本
- 助手函数:https://www.kancloud.cn/manual/thinkphp6_0/1037653
- 门面Facade:https://www.kancloud.cn/manual/thinkphp6_0/1037491
- URL访问模式:域名/入口/控制器/操作/参数名/参数...,入口、控制器不填的时候默认index。单个参数无需指定参数名。(参数绑定:https://www.kancloud.cn/manual/thinkphp6_0/1037523)
- Request请求对象:https://www.kancloud.cn/manual/thinkphp6_0/1037516
- Response响应对象:https://www.kancloud.cn/manual/thinkphp6_0/1037525
- 在Tp6里不能通过header函数设置响应头,只能通过response对象。
2.控制器以及多应用
- 官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037510
- Tp6支持任意的多级路由器,访问时URl格式为:host/one.two.three/methods
- 可以通过路由的方式精简URL。路由不能针对整个控制器路由。
- 跨域访问:https://www.kancloud.cn/manual/thinkphp6_0/1037507
多应用模式
多应用模式部署后,记得删除app目录下的controller目录(系统根据该目录作为判断是否单应用的依据)。
在mac或者linux环境下面,注意需要设置runtime目录权限为777。
3.视图
视图的目录规范:https://www.kancloud.cn/manual/thinkphp6_0/1037611
视图模板赋值与输出:https://www.kancloud.cn/manual/thinkphp6_0/1037609
模板开发文档:https://www.kancloud.cn/manual/think-template
代码语言:javascript复制// 模板变量赋值
View::assign('name','ThinkPHP');
// 或者批量赋值
View::assign([
'name' => 'ThinkPHP',
'email' => 'thinkphp@qq.com'
]);
// 使用视图输出过滤
return View::filter(function($content){
return str_replace("rn",'',$content);
})->fetch();
可以使用View静态方法或者view()助手函数返回的对象;
模板路径:默认情况下,框架会自动定位你的模板文件路径,优先定位应用目录下的view
目录,这种方式的视图目录下就是应用的控制器目录。(app/(多应用时存在的目录)/controller同级目录的view目录/控制器目录/视图.html);第二种方式是视图文件和应用类库文件完全分离,统一放置在根目录下的view
目录。
表示系统会按照默认规则自动定位视图目录下的模板文件,其规则是:控制器名(小写 下划线)/操作名.html。如果有更改模板引擎的view_depr,改为_后就变成控制器_视图.html;
代码语言:javascript复制/* 指定模板输出 */
return View::fetch('edit');
/*表示调用当前控制器下面的edit模板*/
return View::fetch('member/read');
/*表示调用Member控制器下面的read模板。*/
return View::fetch('admin@member/edit');
/*表示跨应用调用模板*/
4.数据库
原生查询:https://www.kancloud.cn/manual/thinkphp6_0/1037570
代码语言:javascript复制$user=Db::table('$tablename'); /*含前缀*/
$user=Db::name('$name');/*不含前缀*/
在Db类的方法中,name(),会自动加上表前缀,table(),则不会。
链式查询:https://www.kancloud.cn/manual/thinkphp6_0/1037538,如field指定部分字段等等。
select 方法查询结果是一个数据集对象,如果需要转换为数组可以使用(toArray)
find 方法:查询符合条件的第一条数据。select 方法:查询符合条件的所有数据。find只是取一条记录;打印出来的区别只是有个limit 1的限制;
字符串条件查询:whereRaw('type=1 AND status=1'),以及whereOr、whereIn等等
find查询未找到数据是返回null,findOrEmpty未找到数据时返回空数组。insertGetId,插入数据时返回Id
update方法返回影响数据的条数,没修改任何数据返回 0;
fieldRaw方法中可直接使用Mysql函数,fieldRaw('id,SUM(score)');
如果要更新的数据需要使用SQL函数或者其它字段,exp('name','UPPER(name)');
getOptions(),$model_list = User::order();$options = $model_list->getOptions();获取本次查询的条件;
fetchSql(),fetchSql用于直接返回SQL而不是执行查询,适用于任何的CURD操作方法。
buildSql(),返回用于子查询的sql语句
5.引入自定义类库、函数
- 如果你需要在核心之外扩展和使用第三方类库,并且该类库不是通过Composer安装使用,那么可以直接放入应用根目录下面的extend目录下面,该目录是官方建议的第三方扩展类库目录。
- 官方文档说明:https://www.kancloud.cn/manual/thinkphp5/177200
- 强烈建议使用Composer安装和更新扩展类库,ThinkPHP5.0 的扩展类库都采用Composer方式进行安装。
6.扩展和自定义配置目录:
- 5.0.1开始增加了扩展配置目录的概念,在应用配置目录或者模块配置目录下面增加extra子目录,下面的配置文件都会自动加载,无需任何配置。
- Tp6.x的config目录下的所有配置文件系统都会自动读取,不需要手动加载。如果存在子目录,你可以通过Config类的load方法手动加载
- 官方说明文档:https://www.kancloud.cn/manual/thinkphp5/215848
- 自定义函数直接写在application 或app目录下的common.php 即可。
7.数据模型
- 模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写。
- 模型可使用数据库Db的所有方法。
- 模型类定义在app/model目录内,官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037483。
- 模型在控制器中的引入方式有三种,在控制器的开始部分use进来(推荐使用)、使用Loader类加载模型、使用助手函数model(不推荐使用,以防助手函数被覆盖掉)。
- select 方法查询结果是一个数据集对象,如果需要转换为数组可以使用(toArrray()方法)。
- V6.0.3 版本开始,原生查询仅支持Db类操作,不支持在模型中调用原生查询方法(包括query和execute方法)。
8.异常处理
- 官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037615
<?php
/* 全局错误处理 */
if ($e instanceof HttpException) {
if ($e->getStatusCode() == 404) {
return json(["code" => 0, "errMsg" => $e->getMessage()])->code(404);
} else {
return json(["code" => 0, "errMsg" => $e->getMessage()]);
}
} else {
return json(["code" => 0, "errMsg" => $e->getMessage()]);
}
}
9.中间件
中间件主要用于拦截或过滤应用的HTTP请求,并进行必要的业务处理。
全局中间件->应用中间件->路由中间件->控制器中间件;
官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037493
直接使用中间件时需要指定完整的包名 类名,通过middleware.php配置中间件的别名后可直接指定别名。
直接传递参数到控制器;
代码语言:javascript复制public function handle($request, Closure $next)
{
if ('think' == $request->name) {
$request->name = 'ThinkPHP';
}
return $next($request);
}
路由中间件
可以细化到对方法进行中间件控制
10.事件
- 事件相比较中间件的优势是事件比中间件更加精准定位(或者说粒度更细),并且更适合一些业务场景的扩展。例如,我们通常会遇到用户注册或者登录后需要做一系列操作,通过事件系统可以做到不侵入原有代码完成登录的操作扩展,降低系统的耦合性的同时,也降低了BUG的可能性。
- 官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037492
11.数据库事务
什么情况下应该使用事务,当数据库操作结束后,还有其它的非数据库业务流程,失败时数据库操作不应该存在时使用。
Thinkphp6 模型使用事务同DB类一致,实例化后直接调用startTrans、commit、rollback;
回滚只能在Commit之前,Commit之后将无法回滚。
12.数据库加锁
排它锁:Db::name('user')->where('id',1)->lock(true)->find();
共享锁:Db::name('user')->where('id',1)->lock('lock in share mode')->find();
13.Redis的使用
官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037634
官方提供的方法都比较简单易用,当然也可以自己对Redis类进行封装;
路由相关
1.基础知识
官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037494
路由解析的过程一般包含:
- 路由定义:完成路由规则的定义和参数设置;
- 路由检测:检查当前的URL请求是否有匹配的路由;
- 路由解析:解析当前路由实际对应的操作(方法或闭包);
- 路由调度:执行路由解析的结果调度;
- 掌握路由主要是要掌握路由定义及参数设置,其它环节是由系统自动完成的。
路由定义
route目录下的任何路由定义文件都是有效的,分开多个路由定义文件并没有实际的意义,纯粹出于管理方便而已。默认的路由定义文件是route.php,但你完全可以更改文件名,或者添加多个路由定义文件。
1.1 单应用路由
代码语言:javascript复制├─route 路由定义目录
│ ├─route.php 路由定义
│ ├─api.php 路由定义
│ └─... 更多路由定义
1.2 多应用路由
多应用模式,路由定义文件需要放入应用目录下:
代码语言:javascript复制├─app 应用目录
│ ├─app_name 应用目录
│ │ ├─common.php 函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ ├─config 配置目录
│ │ ├─route 路由目录
│ │ │ ├─route.php 路由定义
│ │ │ ├─api.php 路由定义
│ │ │ └─... 更多路由定义
2.注册路由
要使用Route类注册路由必须首先在路由定义文件开头添加引用(定义路由之后,原来的访问地址会自动失效)
代码语言:javascript复制use thinkfacadeRoute;
Route::rule('路由表达式', '路由地址', '请求类型');
// 注册路由到News控制器的read操作
Route::rule('new/:id','News/read');
// 单独指定请求类型鹅快捷方法
Route::快捷方法名('路由表达式', '路由地址');
3.路由类型
- 路由到控制器/操作,路由到blog控制器,Route::get('blog/:id','Blog/read');
- 路由到类的方法,完整类名@方法名,Route::get('blog/:id','appindexserviceBlog@read');
- 重定向路由,Route::redirect('blog/:id', 'http://blog.thinkphp.cn/read/:id', 302);
- 路由到模板,路由到模板文件,Route::view('hello/:name', 'index/hello',[携带的变量]);
- 路由到闭包,Route::get('hello', function () {return 'hello,world!';});
4.路由参数
官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037499
代码语言:javascript复制Route::get('new/:id', 'News/read')
->ext('html')
->https();
路由参数可以混合使用,只要有任何一条参数检查不通过,当前路由就不会生效,继续检测后面的路由规则。
代码语言:javascript复制<?php
Route::get('chat/:user/:id','Index/chat');
public function chat($user, $id)
5.路由中间件
单个路由注册中间件:
代码语言:javascript复制Route::rule('hello/:name','hello')
->middleware(appmiddlewareAuth::class);
路由分组注册中间件:
代码语言:javascript复制Route::group('hello', function(){
Route::rule('hello/:name','hello');
})->middleware(appmiddlewareAuth::class);
使用数组方式,定义多个中间件:
代码语言:javascript复制Route::rule('hello/:name','hello')
->middleware([appmiddlewareAuth::class,appmiddlewareCheck::class]);
6.注解路由
ThinkPHP支持使用注解方式定义路由(也称为注解路由),如果需要使用注解路由需要安装额外的扩展:
代码语言:javascript复制composer require topthink/think-annotation
使用注解定义路由:
代码语言:javascript复制class Index
{
/**
* @param string $name 数据名称
* @return mixed
* @Route("hello/:name")
*/
public function hello($name)
{
return 'hello,'.$name;
}
}
7.路由绑定
把当前的URL绑定到控制器/操作,最多支持绑定到操作级别。
7.1绑定到控制器/操作
代码语言:javascript复制// 绑定当前的URL到 Blog控制器
Route::bind('blog');
// 绑定当前的URL到 Blog控制器的read操作
Route::bind('blog/read');
Request对象
Request对象可通过 thinkfacadeRequest;t或者request()助手函数两种方式获取;
1.Request::has('id','get');
判断参数是否传递,等同于isset(request()->get("id"));
- param 获取当前请求的变量;
- get 获取 $_GET 变量;
- post 获取 $_POST 变量;
- put 获取 PUT 变量;
- delete 获取 DELETE 变量;
- session 获取 SESSION 变量;
- cookie 获取 $_COOKIE 变量;
- request 获取 $_REQUEST 变量;
- server 获取 $_SERVER 变量;
- env 获取 $_ENV 变量;
- route 获取 路由(包括PATHINFO) 变量
- middleware 获取 中间件赋值/传递的变量;
- file 获取 $_FILES 变量;
- all V6.0.8 获取包括 $_FILES 变量在内的请求变量,相当于param file;
2.默认值
Request::get('name','default'); // 返回值为default
3.变量过滤
框架默认没有设置任何全局过滤规则,你可以在appRequest对象中设置filter全局过滤属性;
全局变量过滤方法:Request::filter(['strip_tags','htmlspecialchars']),
获取变量的时候过滤:Request::param('username','','strip_tags,strtolower'); // 获取param变量 并依次调用strip_tags、strtolower函数过滤
4.获取JSON数据
对于body中提交的json对象,你无需使用php://input去获取,可以直接当做表单提交的数据使用,因为系统已经自动处理过了;
5.获取部分参数、排除参数
代码语言:javascript复制/* 设置默认值 */
Request::only(['id'=>0,'name'=>'']);
/* 只获取当前请求的id和name变量*/
Request::only(['id','name']);
/* 只获取GET请求的id和name变量*/
Request::only(['id','name'], 'get');
/* 排除id和name变量*/
Request::except(['id','name']);
6.修饰符
Request::变量类型('变量名/修饰符');
- s 强制转换为字符串类型
- d 强制转换为整型类型
- b 强制转换为布尔类型
- a 强制转换为数组类型
- f 强制转换为浮点类型
7.助手函数
为了简化使用,还可以使用系统提供的input助手函数完成上述大部分功能。https://www.kancloud.cn/manual/thinkphp6_0/1037519#_89
- input('?get.id');//是否存在
- input('param.name'); // 获取单个参数
- input('param.'); // 获取全部参数
- input('');// 获取全部参数input('get.id');// 获取单个参数
- input('get.name','','htmlspecialchars'); // 获取get变量 并用htmlspecialchars函数过滤
- input('post.name','','orgFilter::safeHtml'); // 获取post变量 并用orgFilter类的safeHtml方法过滤
- input('post.ids/a');//变量修饰符
功能总览
- 日志相关功能:https://www.kancloud.cn/manual/thinkphp6_0/1037616
- 错误和调试:https://www.kancloud.cn/manual/thinkphp6_0/1037615、https://www.kancloud.cn/manual/thinkphp6_0/1037618
- 数据验证:https://www.kancloud.cn/manual/thinkphp6_0/1037623
- 系统安全:https://www.kancloud.cn/manual/thinkphp5/268461
- 实用小功能:https://www.kancloud.cn/manual/thinkphp6_0/1037633
- 扩展功能的相关说明:https://www.kancloud.cn/manual/thinkphp5/118129
- Thinkphp部署相关的细节:https://www.kancloud.cn/manual/thinkphp5/129745
使用心得
1.快捷获取当前时间
代码语言:javascript复制/*
* 按照格式化字符获取当前时间
* */
function now($format="Y-m-d H:i:s"){
return date($format,time());
}
3.分页输出
代码语言:javascript复制QdAccount::order('belong', 'desc')
->paginate([
'list_rows' => $json['size'],
'page' => $json['page'],
])->toArray();
//最终输出
{
"total": 2,
"per_page": 30,
"current_page": 1,
"last_page": 1,
"data": [
{
"id": 1,
"mobile": "18273411374",
"password": "123",
"register_time": "2022-07-14 13:31:04"
},
{
"id": 2,
"mobile": "18273411374",
"password": "123",
"register_time": "2022-07-14 13:32:04"
}
]
}
问题总结
1.日常报错
Tp6.0报错Driver [Think] not supported.是因为没有安装tp视图库,安装即可。
代码语言:javascript复制composer require topthink/think-view
文件上传:https://www.kancloud.cn/manual/thinkphp6_0/1037639,文件系统类:https://github.com/ctfang/think-flysystem
在Linux系统上,Thinkphp是区分大小写的。模型名、控制器等必须大小写一致。
Session保存的目录不可写时,将导致session失效。
通过助手函数直接让用户响应下载文件:https://kancloud.cn/manual/thinkphp6_0/1037529
控制器进行响应时,可以携带一个状态码。
Thinkphp通过伪静态重定向,会导致正常访问不存在的资源时也会经过PHP处理。
2. Tp6.1
更新6.1移除了filesystem的库,导致文件上传报错了。安装的时候又报错了。
代码语言:javascript复制require ext-fileinfo * -> it is missing from your system. Install or enable PHP's fileinfo extension.
出现此错误的原因是php.ini中的fileinfo扩展没有开启,安装fileinfo拓展,开启 extension=fileinfo
3.tp6.1问题记录
更新6.1移除了filesystem的库,导致文件上传报错了。好不容易安装了,6.1版本用不了。
最后升级thinkphp到6.1.x-dev版本才解决。
4.字段缓存
ORM:https://www.kancloud.cn/manual/think-orm/1258072
代码语言:javascript复制// 开启字段缓存
'fields_cache' => true,
// 字段缓存路径
'schema_cache_path' => 'path/to/cache',
开启后,会自动生成使用过的数据表字段缓存,如果你更改了数据表的字段及类型,需要清空字段缓存文件。字段缓存采用文件方式保存,路径由schema_cache_path配置参数设置。