zl程序教程

您现在的位置是:首页 >  IT要闻

当前栏目

Thinkphp6学习笔记,持续记录

2023-03-07 09:42:56 时间

官方文档

由此开始: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写入;

\think\middleware\SessionInit::class

config/session.php调整session的有效期;

config/middleware.php新增中间件类的别名

'alias'    => [
      "Token"=>app\middleware\Token::class,
      "BusinessToken"=>app\middleware\BusinessToken::class
],

config/database.php,修改数据库相关的配置信息;

config/filesystem.php,修改自带的文件管理库相关配置;

config/app.php ,修改应用相关配置(是否显示错误信息等等);

config/cache.php,配置redis等缓存数据库;

.env,修改调试的相关配置信息;

app/ExceptionHandle.php,修改默认错误信息输出的默认模板;

细节总结

1.基本

  1. 助手函数:https://www.kancloud.cn/manual/thinkphp6_0/1037653
  2. 门面Facade:https://www.kancloud.cn/manual/thinkphp6_0/1037491
  3. URL访问模式:域名/入口/控制器/操作/参数名/参数...,入口、控制器不填的时候默认index。单个参数无需指定参数名。(参数绑定:https://www.kancloud.cn/manual/thinkphp6_0/1037523
  4. Request请求对象:https://www.kancloud.cn/manual/thinkphp6_0/1037516
  5. Response响应对象:https://www.kancloud.cn/manual/thinkphp6_0/1037525
  6. 在Tp6里不能通过header函数设置响应头,只能通过response对象。

2.控制器以及多应用

  1. 官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037510
  2. Tp6支持任意的多级路由器,访问时URl格式为:host/one.two.three/methods
  3. 可以通过路由的方式精简URL。路由不能针对整个控制器路由。
  4. 跨域访问: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

// 模板变量赋值
View::assign('name','ThinkPHP');
// 或者批量赋值
View::assign([
     'name'  => 'ThinkPHP',
     'email' => 'thinkphp@qq.com'
]);

// 使用视图输出过滤
return View::filter(function($content){
        return str_replace("\r\n",'',$content);
    })->fetch();

可以使用View静态方法或者view()助手函数返回的对象;

模板路径:默认情况下,框架会自动定位你的模板文件路径,优先定位应用目录下的view目录,这种方式的视图目录下就是应用的控制器目录。(app/(多应用时存在的目录)/controller同级目录的view目录/控制器目录/视图.html);第二种方式是视图文件和应用类库文件完全分离,统一放置在根目录下的view目录。

表示系统会按照默认规则自动定位视图目录下的模板文件,其规则是:控制器名(小写+下划线)/操作名.html。如果有更改模板引擎的view_depr,改为_后就变成控制器_视图.html;

/* 指定模板输出 */
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

$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.引入自定义类库、函数

  1. 如果你需要在核心之外扩展和使用第三方类库,并且该类库不是通过Composer安装使用,那么可以直接放入应用根目录下面的extend目录下面,该目录是官方建议的第三方扩展类库目录。
  2. 官方文档说明:https://www.kancloud.cn/manual/thinkphp5/177200
  3. 强烈建议使用Composer安装和更新扩展类库,ThinkPHP5.0+的扩展类库都采用Composer方式进行安装。

6.扩展和自定义配置目录:

  1. 5.0.1开始增加了扩展配置目录的概念,在应用配置目录或者模块配置目录下面增加extra子目录,下面的配置文件都会自动加载,无需任何配置。
  2. Tp6.x的config目录下的所有配置文件系统都会自动读取,不需要手动加载。如果存在子目录,你可以通过Config类的load方法手动加载
  3. 官方说明文档:https://www.kancloud.cn/manual/thinkphp5/215848
  4. 自定义函数直接写在application 或app目录下的common.php 即可。

7.数据模型

  1. 模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写。
  2. 模型可使用数据库Db的所有方法。
  3. 模型类定义在app/model目录内,官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037483。
  4. 模型在控制器中的引入方式有三种,在控制器的开始部分use进来(推荐使用)、使用Loader类加载模型、使用助手函数model(不推荐使用,以防助手函数被覆盖掉)。
  5. select 方法查询结果是一个数据集对象,如果需要转换为数组可以使用(toArrray()方法)。
  6. V6.0.3+版本开始,原生查询仅支持Db类操作,不支持在模型中调用原生查询方法(包括query和execute方法)。

8.异常处理

  1. 官方文档: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配置中间件的别名后可直接指定别名。

直接传递参数到控制器;

public function handle($request, \Closure $next)
                {
                    if ('think' == $request->name) {
                    $request->name = 'ThinkPHP';
                }

                    return $next($request);
                }

路由中间件

可以细化到对方法进行中间件控制

10.事件

  1. 事件相比较中间件的优势是事件比中间件更加精准定位(或者说粒度更细),并且更适合一些业务场景的扩展。例如,我们通常会遇到用户注册或者登录后需要做一系列操作,通过事件系统可以做到不侵入原有代码完成登录的操作扩展,降低系统的耦合性的同时,也降低了BUG的可能性。
  2. 官方文档: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 单应用路由

├─route                 路由定义目录
│  ├─route.php          路由定义
│  ├─api.php            路由定义
│  └─...                更多路由定义

1.2 多应用路由

多应用模式,路由定义文件需要放入应用目录下:

├─app           应用目录
│  ├─app_name           应用目录
│  │  ├─common.php      函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─view            视图目录
│  │  ├─config          配置目录
│  │  ├─route           路由目录
│  │  │  ├─route.php    路由定义
│  │  │  ├─api.php      路由定义
│  │  │  └─...          更多路由定义

2.注册路由

要使用Route类注册路由必须首先在路由定义文件开头添加引用(定义路由之后,原来的访问地址会自动失效)

use think\facade\Route;
Route::rule('路由表达式', '路由地址', '请求类型');
// 注册路由到News控制器的read操作
Route::rule('new/:id','News/read');
// 单独指定请求类型鹅快捷方法
Route::快捷方法名('路由表达式', '路由地址');

3.路由类型

  • 路由到控制器/操作,路由到blog控制器,Route::get('blog/:id','Blog/read');
  • 路由到类的方法,\完整类名@方法名,Route::get('blog/:id','\app\index\service\Blog@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

Route::get('new/:id', 'News/read')
    ->ext('html')
    ->https();

路由参数可以混合使用,只要有任何一条参数检查不通过,当前路由就不会生效,继续检测后面的路由规则。

<?php

Route::get('chat/:user/:id','Index/chat');
public function chat($user, $id)

5.路由中间件

单个路由注册中间件:

Route::rule('hello/:name','hello')
	->middleware(\app\middleware\Auth::class);

路由分组注册中间件:

Route::group('hello', function(){
	Route::rule('hello/:name','hello');
})->middleware(\app\middleware\Auth::class);

使用数组方式,定义多个中间件:

Route::rule('hello/:name','hello')
	->middleware([\app\middleware\Auth::class,\app\middleware\Check::class]);

6.注解路由

ThinkPHP支持使用注解方式定义路由(也称为注解路由),如果需要使用注解路由需要安装额外的扩展:

composer require topthink/think-annotation

使用注解定义路由:

class Index
{
    /**
     * @param  string $name 数据名称
     * @return mixed
     * @Route("hello/:name")
     */
	public function hello($name)
    {
    	return 'hello,'.$name;
    }
}

7.路由绑定

把当前的URL绑定到控制器/操作,最多支持绑定到操作级别。

7.1绑定到控制器/操作

// 绑定当前的URL到 Blog控制器
Route::bind('blog');
// 绑定当前的URL到 Blog控制器的read操作
Route::bind('blog/read');

Request对象

Request对象可通过 think\facade\Request;t或者request()助手函数两种方式获取;

1.Request::has('id','get');

判断参数是否传递,等同于isset(request()->get("id"));

  1. param 获取当前请求的变量;
  2. get 获取 $_GET 变量;
  3. post 获取 $_POST 变量;
  4. put 获取 PUT 变量;
  5. delete 获取 DELETE 变量;
  6. session 获取 SESSION 变量;
  7. cookie 获取 $_COOKIE 变量;
  8. request 获取 $_REQUEST 变量;
  9. server 获取 $_SERVER 变量;
  10. env 获取 $_ENV 变量;
  11. route 获取 路由(包括PATHINFO) 变量
  12. middleware 获取 中间件赋值/传递的变量;
  13. file 获取 $_FILES 变量;
  14. all V6.0.8+ 获取包括 $_FILES 变量在内的请求变量,相当于param+file;

2.默认值

Request::get('name','default'); // 返回值为default

3.变量过滤

框架默认没有设置任何全局过滤规则,你可以在app\Request对象中设置filter全局过滤属性;

全局变量过滤方法:Request::filter(['strip_tags','htmlspecialchars']),

获取变量的时候过滤:Request::param('username','','strip_tags,strtolower'); // 获取param变量 并依次调用strip_tags、strtolower函数过滤

4.获取JSON数据

对于body中提交的json对象,你无需使用php://input去获取,可以直接当做表单提交的数据使用,因为系统已经自动处理过了;

5.获取部分参数、排除参数 

/* 设置默认值 */
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::变量类型('变量名/修饰符');

  1. s 强制转换为字符串类型
  2. d 强制转换为整型类型
  3. b 强制转换为布尔类型
  4. a 强制转换为数组类型
  5. 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','','org\Filter::safeHtml'); // 获取post变量 并用org\Filter类的safeHtml方法过滤
  • input('post.ids/a');//变量修饰符

功能总览

  1. 日志相关功能:https://www.kancloud.cn/manual/thinkphp6_0/1037616
  2. 错误和调试:https://www.kancloud.cn/manual/thinkphp6_0/1037615https://www.kancloud.cn/manual/thinkphp6_0/1037618
  3. 数据验证:https://www.kancloud.cn/manual/thinkphp6_0/1037623
  4. 系统安全:https://www.kancloud.cn/manual/thinkphp5/268461
  5. 实用小功能:https://www.kancloud.cn/manual/thinkphp6_0/1037633
  6. 扩展功能的相关说明:https://www.kancloud.cn/manual/thinkphp5/118129
  7. Thinkphp部署相关的细节:https://www.kancloud.cn/manual/thinkphp5/129745

使用心得

1.快捷获取当前时间

/*
 * 按照格式化字符获取当前时间
 * */
function now($format="Y-m-d H:i:s"){
  return date($format,time());
}

3.分页输出

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视图库,安装即可。

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的库,导致文件上传报错了。安装的时候又报错了。

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

// 开启字段缓存
'fields_cache'      => true,
// 字段缓存路径
'schema_cache_path' => 'path/to/cache',

开启后,会自动生成使用过的数据表字段缓存,如果你更改了数据表的字段及类型,需要清空字段缓存文件。字段缓存采用文件方式保存,路径由schema_cache_path配置参数设置。