一. 初识佳人 (ThinkPHP 5.0 基本)
TP5 环境要求
PHP >= 5.4.0
PDO PHP Extension PDO类
MBstring PHP Extension 多字节字符串函数
查询文档手册中mb字符串函数
CURL PHP Extension 钩子/爬虫
目录结构
1).部署框架 目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13
| tp5 ├─application 应用目录 ├─extend 扩展类库目录(可定义) ├─public 网站对外访问目录 ├─runtime 运行时目录(可定义)(linux777权限) ├─vendor 第三方类库目录(Composer) ├─thinkphp 框架核心目录 ├─build.php 自动生成定义文件(参考) ├─composer.json Composer定义文件 ├─LICENSE.txt 授权说明文件 ├─README.md README 文件 └─think 命令行工具入口 !(如果在linux环境下面的话,需要给runtime目录755权限)
|
1 2 3 4 5 6
| 目录 说明 常量 tp5 项目根目录 ROOT_PATH tp5/application 应用目录 APP_PATH tp5/thinkphp 框架核心目录 THINK_PATH tp5/exend 应用扩展目录 EXTEND_PATH tp5/vendor Composer扩展目录 VENDOR_PATH
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ├─thinkphp 框架系统目录(请只读) │ ├─lang 语言包目录 │ ├─library 框架核心类库目录 │ │ ├─think think 类库包目录 │ │ └─traits 系统 traits 目录 │ ├─tpl 系统模板目录(修改请保留源文件) │ │ │ ├─.htaccess 用于 apache 的重写 │ ├─.travis.yml CI 定义文件 │ ├─base.php 框架基础文件 │ ├─composer.json composer 定义文件 │ ├─console.php 控制台入口文件 │ ├─convention.php 惯例配置文件 │ ├─helper.php 助手函数文件(可选) │ ├─LICENSE.txt 授权说明文件 │ ├─phpunit.xml 单元测试配置文件 │ ├─README.md README 文件 │ └─start.php 框架引导文件
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ├─application 应用目录(可设置) │ ├─index 模块目录(可更改)(可多模块) │ │ ├─config.php 模块配置文件 │ │ ├─common.php 模块公共文件 │ │ ├─controller 控制器目录 │ │ ├─model 模型目录 │ │ └─view 视图目录 │ │ │ ├─command.php 命令行工具配置文件 │ ├─common.php 应用公共文件 │ ├─config.php 应用配置文件 │ ├─tags.php 应用行为扩展定义文件 │ ├─database.php 数据库配置文件 │ └─route.php 路由配置文件
|
架构总览
生命周期
入口文件 / 公共资源说明
public/static中的gitignore文件声明了所有该文件中的数据全部不会上传到git
方便采用本地调试 , 远程部署的设计结构(CDN服务/OSS)
URL访问
调试模式
配置: 编程过程中只需要关注应用配置和模块配置就够了
application/config.php中配置
开发过程中开启app_debug, app_trace(配置位置为console台),
注意: 上线后必须将配置还原; 该配置打开可能会影响接口的调试和正常运行
phpstorm中可以完成git操作,并配合码云安装IDEA插件
控制器
新建模块
php think build --module admin
新建控制器
php think make:controller admin/User --plain
视图
PHPstorm快捷键:
美化 :Ctrl+Alt+L
Ctrl+Alt+Shift+L
二. 尝试接近 (CURD 操作 Db类)
数据库配置
application/database.php
本地使用时使用服务器ip , 和服务器专用账号, 上传时修改为本地ip
3306
表前缀
查询数据
1 2 3 4 5 6 7 8 9 10 11
| use think\Db;
//原生sql $list = Db::query('select * from users'); $list = Db::query('select * from users where id=?', [3]);
//DB类 $list = Db::table('users')->order(['id'=>'desc'])->select();
//助手函数(无需use think\Db 也可以使用) $list = db('users')->order(['id'=>'desc'])->select();
|
新增数据
1 2 3 4 5 6 7 8 9 10 11 12
| //原生sql $list = Db::execute("insert into users (id, name, age) values (null,'西格玛','22')"); $list = Db::execute('insert into users (id, name, age) values (:id, :name, :age)', ['id' => null, 'name' => 'tiger', 'age' => 13]);
//DB类 $list = Db::table('users')->data(['name'=>'cat','age'=>22])->insert(); $list = Db::table('users')->insert(['name'=>'cat','age'=>22]); $list = Db::table('users')->insertGetId(['name'=>'cat1','age'=>12]);
//助手函数 $list = db('users')->insert(['name'=>'cat1','age'=>12]); $list = db('users')->insertGetId(['name'=>'cat3','age'=>12]);
|
删除数据
1 2 3 4 5 6 7 8 9 10
| //原生sql $list = Db::execute('delete from users where name="cat1"');
//DB类 $list = Db::table('users')->delete(80); #主键才可以这么玩 $list = Db::table('users')->where(['name'=>'cat'])->delete(); $list = Db::table('users')->where('name','cat')->delete();
//助手函数 $list = db('users')->where('name','tiger')->delete();
|
更新数据
1 2 3 4 5 6 7 8 9
| //原生sql $list = Db::execute('update users set age=33 where name="西格玛"');
//DB类 $list = Db::table('users')->where(['id'=>'77'])>update(['name'=>'daboluo','age'=>'11']); $list = Db::table('users')->where('id',77)->update(['name'=>'dalao','age'=>'11']);
//助手函数 $list = db('users')->where('id',77)->update(['name'=>'dalao01','age'=>'11']);
|
若设置了表前缀功能 , 将table替换为name即可正常使用
三. 探索深入 (路由)
1.默认的URL规则
2.路由文件
1.配置文件目录
application/config.php
1 2 3 4 5
| 推荐使用强制路由模式,配置后不再使用pathinfo格式的路径模式 // 是否开启路由 'url_route_on' => true, // 是否强制使用路由 'url_route_must' => true,
|
2.路由设置目录
application/route.php
1 2 3
| use think\Route //设置路由格式 Route::get('/','index/index/index');
|
3.路由概念/规则
1 2 3 4 5 6 7
| 从规则上区分 路由分为: 动态路由 和 静态路由 两种 从设置方式上 路由分为: 动态注册 和 静态注册 两种
路由规则中 包含变量的 就是动态路由,没有包含任何变量的称为静态路由. 在路由文件中 return数组的 路由形式, 称之为 静态注册 使用Route类的方法 注册的路由 称之为 动态注册(5.0推荐) 以上两者 可同时使用.
|
3.定义路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| use think\Route //设置路由格式 Route::get('/','index/index/index'); Route::post('ppp','index/index/ppp'); //无参数模式 Route::get('/user','index/index/user'); //必须传参数模式 Route::get('/user/:id','index/index/user'); //可有可无参数模式 Route::get('/user/[:id]','index/index/user'); //匹配参数(只能匹配指定的参数,多了报错) Route::get('/user/[:id]$','index/index/user'); //闭包 Route::get('/user:id',function($id){ //执行体 });
|
4.闭包定义
5.路由参数
1 2 3
| // 动态注册 // Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)'); Route::get('/userlist','admin/user/index',['ext'=>'html|shtml']); #限制后缀名
|
6.变量规则
php think make:controller index/Blog --plain
1 2 3 4 5 6 7 8 9 10 11 12 13
| 若使用非路由模式,真实访问路径为: http://www.tp5.com/index/blog/index/id/123 http://www.tp5.com/index/blog/read/name/naxx http://www.tp5.com/index/blog/article/year/2015/month/11/day/20
使用路由控制 Route::get('/blog/:id$','index/blog/index',[],['id'=>'\d+']); Route::get('blog/:name$','index/blog/read',[],['name'=>'\w+']); Route::get('/blog/:year/:month/:day','index/blog/article',[],['year'=>'\d{4}','month'=>'\d{2}','day'=>'\d{2}']); 之后的路由路径变为: http://www.tp5.com/blog/22 http://www.tp5.com/blog/anna http://www.tp5.com/blog/2015/12/12
|
解决路由拦截的方法有两种 , 一种是将拦截范围越大的路由越向后移, 一种是在路由路径后加 $ 截断
7.路由分组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| // 路由分组用来处理同一个模块下的不同路由 Route::group('blog', [ ':id$' => [ 'index/blog/index', ['get'], ['id' => '\d+'] ], ':name$' => [ 'index/blog/read', ['get'], ['name' => '\w+'] ], ':year/:month/:day' => [ 'index/blog/article', ['get'], ['year' => '\d{4}', 'month' => '\d{2}', 'day' => '\d{2}'] ], ]);
|
8.生成URL地址
使用函数方法url()
或Url::bulid()
1 2 3 4 5 6 7 8 9 10 11 12
| use think\Url; echo Url::build('index/index/user','id=4444'); # /user/4444.html echo Url::build('index/index/user',['id'=>'43']); # /user/43.html // 多参数模式 echo Url::build('index/blog/read',['name'=>'annakalina'],'xhtml',true); # http://www.tp5.com/blog/annakalina.xhtml echo Url::build('index/blog/read',['name'=>'annakalina'],'xhtml','www.hao123.com'); # http://www.hao123.com/blog/annakalina.xhtml echo Url::build('index/blog/read@www.hao123.com',['name'=>'annakalina'],'xhtml'); # http://www.hao123.com/blog/annakalina.xhtml
|
第一个参数为pathinfo路径 , 第二个参数为参数 , 第三个参数为扩展名 , 第四个参数为域名(true表示当前域名 , 也可以写入其他域名)
四. 正式交往 (控制器)
控制器概念
- 接收路由分配过来的请求
- 接收各种的参数
- 调用模型 取得数据
- 调用模版 输出页面
- 业务逻辑 流程控制/分支/循环.
- 业务分层
控制器的定义
控制器初始化
__construct()可能覆盖掉继承的父类同名方法,
应使用tp5中的_initialize()方法
前置操作: $beforeActionList
1 2 3 4 5 6 7 8
| // ['except' => '方法名,方法名'] #除了指定的方法之外都执行 // ['only' => '方法名,方法名'] #只有指定的方法可以执行 // 实例: protected $beforeActionList = [ 'first', 'second' => ['except'=>'hello'], 'third' => ['only'=>'hello,data'], ]
|
跳转和重定向
- 页面 跳转(存在缓冲时间)jump
1 2 3
| use think\Controller; return $this->success('程序执行成功','admin/user/index'); return $this->error('程序执行失败','admin/user/index');
|
第二个参数在路由表中包含指定路由的情况下可以直接写pathinfo路径
1 2 3 4 5 6 7 8 9 10
| 更改固有模板 模板路径: thinkphp/tpl/dispatch_jump.tpl 复制到模板所在目录,修改模板所在目录config.php文件 //配置文件 return [ 'dispatch_error_tmpl' => APP_PATH . 'admin/view/index/jump.html', //默认成功跳转对应的模板文件 'dispatch_success_tmpl' => APP_PATH . 'admin/view/index/jump.html', ]; 即完成了更换模块模板文件的操作
|
- 重定向(直接转)redirect
1 2 3
| use think\Controller; return $this->redirect('index/index/user','id=5'); return $this->redirect('http://bilibili.com');
|
空操作
空控制器
对于混合路由有效 , 访问到不存在的方法和类时触发
五. 执子之手
(增删改查 用户管理实例 RESTful资源控制器)
生成 rest模块的 User资源控制器
php think build --module rest
php think make:controller rest/User
RESTful架构说明
www.ruanyifeng.com/blog/2011/09/restful.html
www.ruanyifeng.com/blog/2014/05/restful_api.html
www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html

注册资源路由
1 2
| 在路由表中添加 Route::resource('users','rest/user');
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // 动态注册 // Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)'); 路由规则:URL访问规则(包括静态规则和动态规则),只有符合规则的路由才能正确访问; 路由地址:实际访问的地址(可以是控制器操作、类的方法或者闭包); 请求类型:表示当前路由生效使用的请求类型,包括GET/POST/PUT/DELETE等,如果希望任何请求都能访问使用*号(默认值)。 路由参数:路由匹配的条件约束或设置参数(用于检测或者解析); 路由变量:路由规则里面的动态变量以及PATH_INFO里面的参数都称之为路由变量; 变量规则:路由规则中的变量的匹配规则(正则表达式);
支持任意请求规则 Route::rule('new/:id','News/update'); 定义GET请求路由规则 Route::get('new/:id','News/read'); 定义POST请求路由规则 Route::post('new/:id','News/update'); 定义PUT请求路由规则 Route::put('new/:id','News/update'); 定义DELETE请求路由规则 Route::delete('new/:id','News/delete'); 所有请求都支持的路由规则 Route::any('new/:id','News/read');
|
RESTful实例
- index 显示资源列表
- create 显示创建资源表单页
- save 保存新建的资源
- read 显示指定的资源
- edit 显示编辑资源表单页
- update 保存更新的资源
- delete 删除指定资源
使用实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // 在User.php中获取数据,并使用模板 $list = Db::name('user') ->field(['id', 'name']) ->order('id', 'asc') ->select();
return view('user/index', [ 'title' => '用户列表', 'list' => $list, ]); // 在本模块view目录下创建模板(view/user/index.html) // 引入css,js文件 {css href="./static/css/bootstrap.min.css"} {css href="__INDEX__rest.css"} {js href="__JS__jquery.min.js"} {js href="__JS__bootstrap.min.js"}
|
1 2 3 4 5 6 7 8
| #引入文件时或在配置中定义常量 // 视图输出字符串内容替换 'view_replace_str' => [ '__INDEX__' => '/static/index/', '__CSS__' => '/static/index/css/', '__JS__' => '/static/index/js/', ], 则变为{css href="__CSS__bootstrap.min.css"}
|
注意: 在模板中使用PHP函数时需要在其前添加冒号
{:url()}
遍历 {volist name="list" key="k" id="v"}{/volist}
1 2 3 4 5 6 7 8
| phpstorm快捷键 Alt+J 快速多选后面的选中元素 Ctrl+Alt+L 快速格式化代码 Ctrl+D 复制指定代码行 Ctrl+Shift+↑/↓ 上下移动代码位置
Alt+←/→ 切换代码窗口 Alt+↑/↓ 快速切换方法
|
六. 人造人计划 (数据库 Db类)
数据库使用的补充
使用框架开发应用,一般不需要 直接操作数据库,而是通过 框架封装好的 数据库中间层 对数据库进行操作。
这样的好处 主要有两个:
一是简化数据库操作,二是做到跨数据库的一致性。
这种设计的中间层 通常称之为 数据库访问抽象层,简称数据访问层(DAL),ThinkPHP5的数据访问层 是基于PHP内置的PDO对象实现。一般抽象层本身 并不直接操作数据库,而是通过 驱动来实现具体的数据库操作。
php think make:controller admin/Test –plain
查询相关
2.1. 快捷查询
2.2. 批量查询
2.3. 区间查询
2.4. 多表查询
1). 手动多表
2). JOIN
3). 视图
2.5. 聚合查询
2.6. 子查询
1.fetchSql 方式
2.buildSql 方式
七. 新生 (模型 Model)
ThinkPHP5.0的模型是一种对象-关系映射(Object/Relation Mapping,简称ORM)的封装,
并且提供了简洁的ActiveRecord实现。一般来说,每个数据表会和一个“模型”对应。
ORM的基本特性就是表映射到模型,记录映射到模型对象实例,字段映射到对象属性。
模型是一种对象化的操作封装,而不是简单的CURD操作,简单的CURD操作直接使用前面提过的Db类即可。
模型类和Db类的区别主要在于对象及业务逻辑的封装,Db类的查询默认返回的是数组(或者集合),而模型类返回的是当前的模型对象实例(或者集合),模型是比Db类更高级的数据封装,支持模型关联、模型事件和业务(逻辑)方法。
php think make:model rest/User