2021-2-15-thinkphp6.0
composer、规范、url访问方式、控制器、连接数据库、数据操作、模型、路由
composer
php5.3以上的一个依赖管理工具,但不是包管理器。windows上下载exe文件后,点击下一步直至完成安装。
1)使用阿里云镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
2)创建thinkPhp6.0项目
composer create-project topthink/think tp
3)启动项目
(1)进入目录
cd tp
(2)启动
php think run
规范
1)目录和文件
(1)目录名,小写+下划线
(2)类库和函数文件统一以.php为后缀
(3)类的文件名军以命名空间定义,且命名空间的路径和类库文件所在路径一直
(4)类文件采用驼峰命名,其他采用小写加下划线命名
(5)类名和文件名保持一致
2)函数、类、属性
(1)类名使用大驼峰
(2)函数名使用小写加下划线
(3)方法和属性使用小驼峰
3)常量与配置
常量和环境变量,以大写字母和下划线命名
配置参数以小写字母和下划线命名
4)数据表和字段
均使用小写加下划线方式命名
url访问方式
1)多APP
IP:prot/appName/className/methodName/argName/argValue
方法名是index可省略方法名
2)单APP
IP:prot/className/methodName/argName/argValue
方法名是index可省略方法名
3)index.php省略
appache的httpd.conf中打开mod_rewrite.so模块,将AllowOverride的None改为All
控制器
1
定义
<?php
namespace app\controller;
use app\BaseController;
class HelloWorld extends BaseController
{
public function hello()
{
return "方法名:".$this->request->action()."路径:".$this->app->getBasePath();
}
}
2
控制器目录
控制器目录可自定义,在文件app/config/routee.php中
return[
'controller_layer' => 'controller',
]
3
多级控制器
在控制器目录下创建文件夹,将控制器放到文件夹内。如创建目录group,目录下放一个名为HelloWorld的控制器,里面有个hello的方法,此时访问路径为url:port/group.HelloWorld/hello
4
渲染输出
1)使用return
2)使用json函数
3)中断执行使用halt函数
5
自定义错误页面
在控制器目录下,建一个名为Error的文件和类,定义好index方法。当请求未找到控制器后,会使用该控制器,如果控制器中没有对应的方法,会报错。
<?php
namespace app\controller;
use app\BaseController;
class Error extends BaseController
{
public function index()
{
return "访问路径不存在";
}
}
连接数据库
1)配置
配置文件database.php中进行配置
2)调用数据库
<?php
namespace app\controller;
use app\BaseController;
use think\facade\Db;
class Test extends BaseController
{
public function index()
{
$users = Db::table("tb_user")->select();
return json($users);
}
}
3)配置多数据库
(1)database.php文件
<?php
use think\facade\Env;
return [
// 默认使用的数据库连接配置
'default' => Env::get('database.driver', 'mysql'),
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段
// true为自动识别类型 false关闭
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 数据库连接配置信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => Env::get('database.type', 'mysql'),
// 服务器地址
'hostname' => Env::get('database.hostname', '127.0.0.1'),
// 数据库名
'database' => Env::get('database.database', 'test'),
// 用户名
'username' => Env::get('database.username', 'root'),
// 密码
'password' => Env::get('database.password', ''),
// 端口
'hostport' => Env::get('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => Env::get('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => Env::get('database.prefix', ''),
// 数据库调试模式
'debug' => Env::get('database.debug', true),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 字段缓存路径
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
],
'mysql_deepin' => [//新增的配置
// 数据库类型
'type' => Env::get('database.type', 'mysql'),
// 服务器地址
'hostname' => Env::get('database.hostname', '192.168.50.33'),
// 数据库名
'database' => Env::get('database.database', 'test'),
// 用户名
'username' => Env::get('database.username', 'root'),
// 密码
'password' => Env::get('database.password', '123456'),
// 端口
'hostport' => Env::get('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => Env::get('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => Env::get('database.prefix', ''),
// 数据库调试模式
'debug' => Env::get('database.debug', true),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 字段缓存路径
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
],
// 更多的数据库配置信息
],
];
(2)控制器中
<?php
namespace app\controller;
use app\BaseController;
use think\facade\Db;
class Test extends BaseController
{
public function multyDb()
{
$orgs = Db::connect("mysql_deepin")->table("tb_org")->select();
return json($orgs);
}
}
访问http://127.0.0.1/Test/multyDb即可看到返回的数据
4)使用Model
(1)定义model类
需创建好一个与controller同父级的目录model,里面防止model的类
<?php
namespace app\model;
use think\Model;
class User extends Model{
protected $connection="mysql";//设置数据源,省略后会连接默认数据源
}
注意:使用model的时候,会通过类名取关联数据库中的表,该类名为USER,关联的是user表,如果数据库中的表名为tb_user,需要取配置文件中设置表的前缀为“tb_”
(2)使用
<?php
namespace app\controller;
use app\BaseController;
use app\model\User;
class Test extends BaseController
{
public function testModel()
{
$users = User::select();
return json($users);
}
}
数据操作
1
查询(Array对象)
1)单条数据查询
//省略其他代码
Db::table("tb_user")->where('id',1)->find();//没查到数据时,返回null
Db::getLastSql();//得到最近一条SQL查询的原生语句
//省略其他代码
Db::table("tb_user")->where('id',1)->findOrFail();//没查到数据时抛出一个异常
//省略其他代码
Db::table("tb_user")->where('id',1)->findOrEmpty();//没查到数据时返回一个空数据
2)数据集查询(Collection对象)
//省略其他代码
Db::table("tb_user")->select();//获取到的时多行数据
//省略其他代码
Db::table("tb_user")->where('id',1)->selectOrFail();//没查到数据时抛出一个异常
//省略其他代码
$users = Db::table("tb_user")->select()->toArray();//转换成数据
dump($users);//查询详细
3)忽略前缀
//省略其他代码
$users = Db::name("user")->select();//表名为tb_user,但需确保配置文件中配置好前缀
4)获取单列值
//省略其他代码
Db::table("tb_user")->where('id',1)->value('user_name');//返回满足where条件这一行的列明为user_name的数据
5)获取多列值
//省略其他代码
Db::table("tb_user")->where('id',1)->column('user_name');
6)分批处理
数据量过大时导致内存开销过大,使用分批处理
Db:table("tb_user")->chunk(3,function($users){
foreach($users as $user){
dump($user);
}
});
7)游标查询
$cursor = Db::table("tb_user")->cursor();
foreach($cursor as $user){
dump($user);
};
8)链式查询
使用where、order等,会得到一个查询对象(Query),最后使用select或find会得到一个最终的数据对象(Array或Collection),在对一个查询对象多次操作时,可将其保存到一个变量中,反复调用,但上一次的where或order会保存在对象中,使用removeOption('where')可清楚掉上一次的操作
2
新增
1)普通新增
//省略其他代码
$user=[
'user_id' => '3',
'user_name' =>"zhang"
];
Db::name("user")->insert($user);//成功后会返回1,表示插入1条数据成功
2)强制新增
//省略其他代码
$user=[
'user_id' => '4',
'user_name' =>"zhang11",
"aaaa"=>"asdsdsd" //不存在的列
];
Db::name("user")->strict(false)->insert($user);//不会报错
3)替换新增
普通情况下插入两条主键相同的数据,会报错。使用replaceh后,插入数据,如果存在则替换,不存在就直接插入
//省略其他代码
$user=[
'user_id' => '3',
'user_name' =>"zhang11",
];
Db::name("user")->replace()->insert($user);//返回2
4)插入数据后返回当前数据id
//省略其他代码
$user=[
'user_id' => '3',
'user_name' =>"zhang11",
];
Db::name("user")->insertGetId($user);//返回id
5)批量插入
//省略其他代码
$users=[
['user_name' =>"zhang123"],
['user_name' =>"zhang1234"]
];
return Db::name("user")->insertAll($users);
6)save方法
//省略其他代码
$user=[
'user_name' =>"zhang"
];
Db::name("user")->save($user);//有主键会进行更新,没有会插入一条新纪录
3
修改
1
基本操作
//省略其他代码
$user=[
'user_name' =>"zhangh"
];
Db::name("user")->where('user_id',3)->update($user);
//修改后返回1,未进行修改返回0
2
省略where
//省略其他代码
$user=[
'user_id'=>'3',
'user_name' =>"zhang"
];
Db::name("user")->update($user);//如果数据中包含主键可省略掉where
3
exp()方法
//省略其他代码
Db::name("user")->where('user_id',3)->exp('user_name','UPPER(user_name)')->update();
4
自增、减
//省略其他代码
Db::name("user")->where('user_id',3)->inc('age')->dec('weight',2)->update();
5
raw()方法
//省略其他代码
Db::name("user")->where('user_id',3)->update([
'user_name'=>Db::row('age+1')
]);
4
删除
1)根据主键删除
//省略其他代码
Db::name("user")->delete(2);
2)根据主键批量删除
//省略其他代码
Db::name("user")->delete([1,2,3]);
3)通过where方法删除
//省略其他代码
Db::name("user")->where('user_id',2)->delete();
4)删除所有数据
//省略其他代码
Db::name("user")->delete(true);
5
查询方式
1)比较查询
//省略其他代码
Db::name("user")->where('user_id','=',76)->find();
Db::name("user")->where('user_id',76)->find();
Db::name("user")->where('user_id','<>',76)->select();
Db::name("user")->where('user_name','like',['zh','huan','or'])->select();
2)模糊查询
//省略其他代码
Db::name("user")->whereLike('user_name',['zh','huan','or'])->select();
Db::name("user")->whereNotLike('user_name',['zh','huan','or'])->select();
3)区间查询
(1)between
//省略其他代码
Db::name("user")->where('user_id','between','19,25')->select();
Db::name("user")->where('user_id','between',[19,25])->select();
Db::name("user")->whereBetween('user_id','19,25')->select();
Db::name("user")->whereNotBetween('user_id','19,25')->select();
(2)in
//省略其他代码
Db::name("user")->where('user_id','in','19,25')->select();
Db::name("user")->whereIn('user_id','19,25')->select();
Db::name("user")->whereNotIn('user_id','19,25')->select();
(3)null
//省略其他代码
Db::name("user")->where('email','null')->select();
Db::name("user")->where('email','not null')->select();
Db::name("user")->whereNull('email')->select();
Db::name("user")->whereNotNull('email')->select();
4)EXP查询
//省略其他代码
Db::name("user")->where('user_id','exp','IN (19,25)')->select();
Db::name("user")->whereExp('user_id','IN (19,25)')->select();
//自定义字段后的SQL语句
6
时间查询
//省略其他代码
Db::name("user")->where('create_time','>','2019-1-1')->select();
Db::name("user")->where('create_time','not between',['2019-1-1','2019-11-11'])->select();
Db::name("user")->whereBetween('create_time',['2019-1-1','2019-11-11'])->select();
//省略其他代码
Db::name("user")->whereTime('create_time','>','2019-1-1')->select();
Db::name("user")->whereBetweenTime('create_time','2019-1-1','2019-11-11')->select();
1)获取当年
//省略其他代码
Db::name("user")->whereYear('create_time')->select();
2)获取上一年
//省略其他代码
Db::name("user")->whereYear('create_time','last year')->select();
3)获取某一年
//省略其他代码
Db::name("user")->whereYear('create_time','2020')->select();
4)查询两小时内
//省略其他代码
Db::name("user")->whereTime('create_time','-2 hours')->select();
7
聚合查询
//省略其他代码
Db::name("user")->count();
Db::name("user")->max('age');
Db::name("user")->min('age');
Db::name("user")->avg('age');
Db::name("user")->sum('age');
8
子查询
1)buildSql
//省略其他代码
$subQuery = Db::name('sex')->field('id')->where('name','男')-buildSql(true);
$result = Db::name('user')->where('id','exp','IN'.$subQuery)->select();
2)函数方式
//省略其他代码
$result = Db::name('user')->where('id','in',function($query){
$query->name('sex')->field('id')->where('name','男');
})->select();
9
原生查询
//省略其他代码
$result1 = Db::query('select * from tb_user');
$result2 = Db::execute('UPDATE tb_user SET user_name="aaaa" WHERE user_id = 1');
10
链式查询
1)where查询
Db::name('user')->where('user_id','>','1')->select();
Db::name('user')->where([
'user_id'=>1
])->select();
Db::name('user')->where([
['user_id','>',1],
['age','>',11]
])->select();
$map[] = ['user_id','>',1];
$map[] = ['age','>',11];
Db::name('user')->where($map)->select();
2)whereRaw查询
Db::name('user')->whereRaw('user_id IN (7,8,9)')->select();
//预处理
Db::name('user')->whereRaw('user_id=:id',['id'=>1])->select();
3)field()
Db::name('user')->field('user_id,user_name')->select();
Db::name('user')->field(['user_id','user_name'])->select();
Db::name('user')->field('user_id,user_name as name')->select();
Db::name('user')->field(['user_id','user_name as name'])->select();
//聚合
Db::name('user')->field('user_id,SUM(age)')->select();
//显示查询所有字段,而不是*
Db::name('user')->field(true)->select();
//排除某一字段
Db::name('user')->withoutField('name')->select();
4)alias
//给数据库起一个别名
Db::name('user')->alias('a')->select();
5)limit
Db::name('user')->limit(0,1)->select();//从0开始
6)page
Db::name('user')->page(1,1)->select();//从1开始
7)order
(1)单字段
Db::name('user')->limit(0,11)->order('id','asc')->select();
(2)多字段
Db::name('user')->limit(0,11)->order(['age'=>'desc','weight'=>'asc'])->select();
(3)orderRaw
Db::name('user')->limit(0,11)->orderRaw('FIELD(user_name,"zhang") DESC')->select();
//SELECT * FROM `tb_user` ORDER BY FIELD(user_name,"zhang") DESC LIMIT 0,11
8)group
Db::name('user')->fieldRaw('user_id,AVG(age)')->group('type')->select();
9)having
Db::name('user')->fieldRaw('user_id,AVG(age)')->having('AVG(age)>0')->group('type')->select();
8)高级查询
(1)普通
Db::name('user')->where('user_name|email','like','%zhang%')
->where('age&weight','>',0)
->select();
//SELECT * FROM `tb_user` WHERE ( `user_name` LIKE '%zhang%' OR `email` LIKE '%zhang%' ) AND ( `age` > 0 AND `weight` > 0 )
//连个where间是and连接
(2)where和whereOr
$map1 = [
['user_name','like','%zh%'],
['email','like','%zh%']
];
$map2 = [
['user_name','like','%huan%'],
['email','like','%c%']
];
$result1 = Db::name('user')->where([$map1,$map2])->select();
//SELECT * FROM `tb_user` WHERE ( `user_name` LIKE '%zh%' AND `email` LIKE '%zh%' ) AND ( `user_name` LIKE '%huan%' AND `email` LIKE '%c%' )
$result1 = Db::name('user')->whereOr([$map1,$map2])->select();
//SELECT * FROM `tb_user` WHERE ( `user_name` LIKE '%zh%' AND `email` LIKE '%zh%' ) OR ( `user_name` LIKE '%huan%' AND `email` LIKE '%c%' )
9)事务
Db::Transaction(function(){
Db::name('user')->where('user_id',1)->save(['money'=>Db::raw('money+3')]);
Db::name('user')->where('user_id',2)->save(['money'=>Db::raw('money-3')]);
});
Db::startTrans();
try{
Db::name('user')->where('user_id',1)->save(['money'=>Db::raw('money+3')]);
Db::name('user')->where('user_id',2)->save(['money'=>Db::raw('money-3')]);
Db::commit();
}catch(Exception $e){
Db::rollback();
}
10)获取器
//对查询结果进行处理
Db::name('user')->withAttr('email',function($value,$data){
return strtoupper($value);
})->select();
11)数据集
(1)获取数据集
$user = Db::name('user')->select();
(2)转换成数组
$user->toArray();
(3)随机打乱
$user->shuffle();
(4)删除最后一个元素
$user->pop();//返回被删除的数据
模型
1
定义
<?php
namespace app\model;
use think\Model;
class Org extends Model{
protected $connection = "mysql_deepin";//指定数据源
protected $name = 'org';//指定模型的后缀,表名=前缀+后缀
protected $pk = 'org_id';//指定主键
protected $table = 'tb_org';//指定表名
}
2
查询
//省略部分代码
//查询
Org::select();
Org::find(1);
Org:where('org_id','>',1)->limit(5)->order('id','desc')->select();
Org:whereIn('org_id',[6,7,8]);
Org::max('id');
3
新增
//省略部分代码
//新增
Org::insert([
'org_id'=>2,
'org_name'=>'机构2'
]);
//模型对象的save方法
$org = new Org();
$org->save(['org_name'=>'机构']);//会自动填充create_time和update_time
$org = new Org();
$org->org_name = '机构a';
$org->save();
//批量新增
$orgs = [
['org_name'=>'机构aaa'],
['org_name'=>'机构bbb']
];
$org = new Org();
$org->saveAll($orgs);//返回新增的两个对象
//静态方法
Org::create([
'org_name'=>'静态机构'
],['org_name'],false);
//参数1是新增的数组,必选
//参数2是允许写入的字段,可选
//参数3为是否replace写入,默认为false
//返回值是新增的数据对象
4
删除
$org = Org::find(1);
$org->delete();
//批量删除
Org::destroy([2,3]);
//条件删除
Org::where('id','=',3).delete();//返回boolean
//闭包方式
Org::destroy(function($query){
$query->where('id'.'>',5);
});
5
修改
$org = Org::find(1);
$org->org_name = '机构a';
$org->save();
//批量修改
$list=[
[
'org_id'=>1,
'org_name'=>'机构3'
],
[
'org_id'=>2,
'org_name'=>'机构4'
]
];
$org = new Org();
$org->saveAll($list);
//静态修改
Org::update([
'org_id'=>1,
'org_name'=>'降级'
]);
Org::update([
'org_name'=>'降级'
],['org_id'=>1]);//主键放到后面的数组
Org::update([
'org_name'=>'降级'
],['org_id'=>1],['org_name']);//第三个参数限制可更新字段为org_name
6
字段缓存问题
每次操作时,都会去查找字段类型,需要将字段信息缓存起来。在config/database.php中开启字段缓存。'field_cache'=>true
7
动态获取器
User::withAttr("email",function($value){
return strtoupper($value);
})->find(4);
8
强制全局范围查询
(1)定义模型
<?php
namespace app\model;
use think\Model;
class User extends Model{
protected $globalScope=['status'];
public function scopeStatus($query){
$query->where('status','>=',0);
}
}
(2)调用
User::withAttr("email",function($value){
return strtoupper($value);
})->find(4);
//SELECT * FROM `tb_user` WHERE `status` >= 0 AND `user_id` = 4 LIMIT 1
//去掉强制
User::withoutGlobalScope()->select();
9
隐藏字段
User::select()->hidden(['money']);
10
仅显示部分字段
User::select()->visible(['money']);
11
自动填充时间
确保database.php中'auto_timestamp' => true
有时需要关闭某个模型中的自动填充功能,在该模型中新增属性protected $autoWriteTimestamp=false
12
设置只读字段(只支持模型)
(1)静态
在模型中新增属性protected $readonly=['username','email']
(2)动态
$user = User::find(4);
$user->email = 'aaa@qq.com';
$user->age = 55;
$user->readonly(['email'])->save();
13
类型转换
在模型中新增属性protecte $type=['user_id'=>'int']
14
废弃字段
在模型中新增属性protected $disuse=['status']
15
存放json
(1)Db操作
//存
$org = [
'org_name'=>"机构谔谔谔",
"list"=>["name"=>"zhang"]
]
Db::name('org')->json(['list'])->save($org);
//取
Db::name('org')->json(['list'])->select();
//根据json属性取数据
Db::name('org')->json(['list'])->where('list->name',"wewqweq")->find();
//修改
$org = Db::name('org')->json(['list'])->find(13);
$org['list'] = ['name'=>'zaaaa'];
Db::name('org')->json(['list'])->save($org);
//修改json中某一个数据
$org = Db::name('org')->json(['list'])->find(13);
$org['list']['name'] = "aaasdsd";
Db::name('org')->json(['list'])->save($org);
(2)模型操作
在模型中定义属性protected %json=['list'];
,就会指定list为存放json的字段
16
软删除
(1)新增字段
表中新增delete_time的字段
(2)模型中开启软删除
新增代码use SoftDelete;
和protected $deleteTime = 'delete_time'
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time';
}
(3)调用
// 软删除
User::destroy(1);
// 真实删除
User::destroy(1,true);
$user = User::find(1);
// 软删除
$user->delete();
// 真实删除
$user->force()->delete();
//注意:已经软删除的数据,需要先还原,再进行真实删除
(4)报错问题
日期字段如果不是int类型会报错,这里需要在模型中放入以下属性
protected $autoWriteTimestamp = 'datetime';
(5)查询软删除数据
User::withTranshed()->select();
User::onlyTranshed()->select();
(6)还原软删除数据
$user = User::onlyTranshed()->find(10);
$user->restore();
17
模型事件
事件 | 描述 | 事件方法名 |
---|---|---|
after_read | 查询后 | onAfterRead |
before_insert | 新增前 | onBeforeInsert |
after_insert | 新增后 | onAfterInsert |
before_update | 更新前 | onBeforeUpdate |
after_update | 更新后 | onAfterUpdate |
before_write | 写入前 | onBeforeWrite |
after_write | 写入后 | onAfterWrite |
before_delete | 删除前 | onBeforeDelete |
after_delete | 删除后 | onAfterDelete |
before_restore | 恢复前 | onBeforeRestore |
after_restore | 恢复后 | onAfterRestore |
在模型类里面定义静态方法来定义模型的相关事件响应
<?php
namespace app\model;
use think\Model;
use app\model\Profile;
class User extends Model
{
public static function onBeforeUpdate($user)
{
if ('thinkphp' == $user->name) {
return false;
}
}
public static function onAfterDelete($user)
{
Profile::destroy($user->id);
}
}
18
关联
1)一对一
(1)模型中新增方法
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model{
protected $pk = 'user_id';
public function detail(){
return $this->hasOne(Detail::class, 'user_id');//指向目标模型,第二个参数是外键
}
}
(2)调用
//取出关联表的字段内容
$user = User::find(1);
echo $user->detail->phone;
//取出一条数据包含detail
$user = User::with('detail')->find(1);
echo $user;
//修改关联表
$user = User::with('detail')->find(1);//with是预加载
$user->detail->save(['phone'=>'18608086840']);
//从user表中查出其关联表detail关联id=1的数据
$user = User::hasWhere('detail',['id'=>1])->find();
//查出其关联表中关联该表的数据记录条数>=2的数据
User::has('detail',">=",2)->select();
//向关联表中新增数据
$user = User::find(1);
$user->detail()->save(['phone'=>122222222]);
//关联删除
$user = User::with('detail')->find(1);
$user->together(['detail'])->delete();
//延时加载
$user = User::find(1);
$user->load();
echo $user->detail->phone;
(3)关联表数据统计
//查出数据包含关联表记录条数
User::withCount(['detail'])->select();
//计算关联表某一字段总和,值赋给totalMoney
User::withSum(['detail'=>'totalMoney'],'money')->select();
2)一对多
(1)定义中间表模型
<?php
namespace app\model;
use think\model\Pivot;
class Access extends Pivot
{
}
(2)定义其中一张主表
<?php
namespace app\model;
use think\Model;
class User extends Model{
public function roles(){
return $this->belongsToMany(Role::class,Access::class,'role_id','user_id');
}
}
(3)调用
//查询
$user = User::find(1);
$roles = $user->roles;
//向关联表插入数据
User::find(1)->roles()->save(['name'=>'测试管理员']);
//向第三张表中插入关联关系
User::find(1)->roles()->save(1);
User::find(1)->roles()->save(Role::find(1));//等同
User::find(1)->roles()->attach(1);//等同
//删除第三张表的关联关系
User::find(1)->roles()->detach(3);
路由
1
路由相关的文件
1)配置文件
配置路由功能的文件,位于config/route.php
2)定义文件
定义路由的文件,位于route/route.php
2
定义路由
(1)普通
Route::rule('user/:id','UserController/getUserById','GET')->pattern(['id'=>'\d+']);//id为参数
(2)全局规则
Route::pattern(['id'=>'\d+'])
(3)多级控制器
Route::rule('detail/:id','goup.Blog/detail');
(4)完整路径控制器
Route::rule('detail/:id','\app\controller\goup.Blog@detail');//用@访问方法
(5)重定向
Route::redirect('ds/:id','http://localhost',302);
3
路由参数检测
1)强制后缀
//强制使用该后缀
Route::rule('detail/:id','goup.Blog/detail')->ext('html');
//禁止使用该后缀
Route::rule('detail/:id','goup.Blog/detail')->denyExt('jpg');
2)强制https
Route::rule('detail/:id','goup.Blog/detail')->https();
3)跨域
Route::rule('detail/:id','goup.Blog/detail')->allowCrossDomain();
Route::rule('detail/:id','goup.Blog/detail')->allowCrossDomain([
'Access-Control-Allow-Origin'=>'http://abc.com'
]);
4
路由分组
Route::group('adress',function(){
Route::rule(':id','Address/details');
Route::rule(':name','Address/read');
})->parttern(['id'=>'\d+','name'=>'\w+']);//省略路由字符串
Route::group('adress',function(){
Route::rule(':id','details');
Route::rule(':name','read');
})->prefix('Address')
->parttern(['id'=>'\d+','name'=>'\w+']);//省略类字符串
5
错误页面
Route::miss('public/miss');//调用Error控制器的miss方法
可全局生效和局部生效,由该段代码的位置决定
获取请求对象
1)注入方式
<?php
namespace app\controller;
use app\BaseController;
use app\Request;//注意
class Index extends BaseController
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function index()
{
dump($this->request);
}
}
2)静态方式
<?php
namespace app\controller;
use app\BaseController;
use think\facade\Request;//注意,调用的是门面里的request
class Index extends BaseController
{
public function index()
{
dump(Request::param('id'));
}
}
3)助手函数
<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
public function index()
{
dump(\request()->param('id'));
}
}
助手函数input
input('?get.id');//判断get下id是否存在
input('?post.id');//判断get下id是否存在
input('param.id');//获取param下id
input('param.id','默认值');//获取,并设置默认值
input('param.id','','htmlspecialchars');//过滤器
中间件
在php中没有AOP,所以对于权限等的控制依赖于中间件。所有的请求都会经过中间件,可对请求进行控制,如权限、日志记录等,相当于过滤器
1
全局中间件
1)定义过滤器
在app目录下创建middleware目录,并在里面放入如下代码
<?php
namespace app\middleware;
class Check
{
public function handle($request, \Closure $next)
{
//前置逻辑
echo $request->url();
$res = $next($request);
//后置逻辑
return $res;
}
public function end(){
echo "结束";
}
}
2)为过滤器定义别名
在config目录下的middleware.php文件中定义
<?php
// 中间件配置
return [
// 别名或分组
'alias' => [
'check' =>[\app\middleware\Check::class]
],
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
'priority' => [],
];
3)注册
在app目录下创建middleware.php文件,写入如下代码
<?php
return [
'check',//通过别名注册过滤器,也可以直接写\app\middleware\Check::class
];
2
路由中间件
定义过滤器、起别名和全局中间件一样,注册只需直接注册到路由上,以下是路由文件,即Route/app.php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Route;
Route::group('article',function(){
Route::rule('','ArticleController/getArticle','GET')->middleware(['check']);//注册中间件
Route::rule('','ArticleController/addArticle','POST');
Route::rule('','ArticleController/updateArticle','PUT');
Route::rule('/list','ArticleController/getArticleList','GET');
Route::rule('/:id','ArticleController/deleteArticle','DELETE');
});
3
控制器中间件
定义过滤器、起别名和全局中间件一样,注册只需将以下属性放到控制器里
protected $middleware = ['check'];
thinkphp访问数据库报错
#0 [0]PDOException in PDOConnection.php line 554
could not find driver
错误原因是php的pdo模块未打开,需要在php.ini文件中找到
;extension=pdo_mysql
去掉左边的';',表示打开注释,开发pdo模块。如果php目录小没有php.ini文件,则需要将php.ini-development另存为php.ini,并进行以上操作,完成后重启项目即可。