写在最前面
差不都10年前就接触过 ThinkPHP,后来再接触 ThinkPHP 已经是到5了。借这次新版本的更新,系统重新再学习下。
如有错误,还请大佬们支出,中国加油!武汉加油!
官方手册
版本要求
PHP7.1+ 官方推荐7.3 MySQL5.7+ 数据库可默认支持JSON数据格式处理
安装
- composer改国内镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
composer create-project topthink/think tp6
cd tp6
composer require topthink/think-view
php think run
开发规范
- 文件夹名:小写和下划线(例:index)
- 类名:首字母大写驼峰式(例:User UserType)
- 函数:小写和下划线(什么是函数?不是方法吗?)
- 方法:首字母小写驼峰式(例:getUserName)
- 属性:首字母小写驼峰式(例:tableName)
- 魔术方法:__全部小写(例:构造方法)
- 常量:全大写加下划线(例:DIRECTORY_SEPARATOR)
- 配置参数:小写加下划线(例:config/app.php)
- 环境变量:全大写加下划线(例:APP_DEBUG)
- 数据表和字段:小写和下划线(例:tp_user user_name)
目录结构
- 默认单应用模式
- 多应用在app下建立(app/index app/admin)
- 默认只有public对外可访问,生产环境部署到服务器,推荐使用宝塔设置访问[运行目录]到public
服务器二级目录配置
这里以宝塔的IIS为例
- 在域名设置伪静态规则
<?xml version="1.0" ?>
<rules>
<rule name="OrgPage_tp6_rewrite_test1" stopProcessing="true">
<match url="^tp6_test1(.*)$"/>
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(.*)$"/>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="tp6_test1/index.php/{R:1}"/>
</rule>
<rule name="OrgPage_tp6_rewrite_test2" stopProcessing="true">
<match url="^tp6_test2(.*)$"/>
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(.*)$"/>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="tp6_test2/index.php/{R:1}"/>
</rule>
</rules>
- 删除 tp 目录下的 web.config
- 在 tp 根目录新建 index.php
<?php
require 'public/index.php';
多应用模式
composer require topthink/think-multi-app
RESTFul
资源控制器php think make:controller api@Index --api
app.php
配置默认访问入口'default_app' => 'api',
跳转操作
TP6 默认不在提供 success、error、redirect和result,需要自行安装
composer require liliuwei/thinkphp-jump
开启调试
- TP6默认未开启调试模式
- 根目录 .example.env 重命名成 .env 就开启调试了(APP_DEBUG = true)
- .env 仅用于本地开发测试,生产环境会被忽略(我试过一次,放在服务器上貌似还是有效的。。。)
- 本地测试 .env 优先级高于 config
获取 .env 配置信息
use think\facade\Env;
Env::get('DATABASE.HOSTNAME');
获取 config 配置信息
use think\facade\Config;
Config::get('app.default_timezone');
Config::get('database.connections.mysql.hostname');
判断配置存在并返回布尔值
Env::has('DATABASE.HOSTNAME');
Config::has('app.default_timezone');
URL 访问模式
网址/控制器/方法/参数名/参数
控制器新建
新建继承基础控制器(BaseController)的 HelloWorld.php 控制器
<?php
namespace app\controller;
use app\BaseController;
class HelloWorld extends BaseController
{
public function index()
{
return 'HelloWorld';
}
}
initialize() 控制器初始化方法,必须继承 BaseController 才能使用
class HelloWorld extends BaseController
{
public function initialize(){
echo 'initialize';
}
}
控制器渲染输出
- 使用方法内的
return
return json($data)
- 中断代码实行不推荐使用
die
或者exit
,推荐助手函数halt()
基础控制器
- 基础控制器提供控制器验证,并注入了
think\App
和think\Request
- 获取控制器方法名
$this->request->action()
- 获取当前实际路径
$this->app->getBasePath()
空控制器
仅用于控制器不存在的错误提示页面 新建 Error.php 控制器
<?php
namespace app\controller;
class Error
{
public function index()
{
return '控制器不存在';
}
}
多级控制器
- 新建多级控制器 app\controller\group\Blog.php
namespace app\controller\group
- 访问 http://127.0.0.1/group.blog/
- 更多方法 http://127.0.0.1/group.blog/read
数据库连接
- .env 优先于 config/database.php 的配置
- 服务器会忽略 .env 直接读取 config/database.php 的配置
门面方式连接数据库
use think\facade\Db;
Db::table('tp6_user')->select();
使用 name 可以省略前缀
use think\facade\Db;
Db::name('user')->select();
使用 connect() 可以切换 database.php 内配置的多个数据库
Db::connect('mysql')->table('tp6_user')->select();
模型连接据库
创建 app/model/User.php
<?php
namespace app\model;
use think\Model;
class User extends Model
{
}
在控制器中使用
use app\model\User as UserModel;
UserModel::select();
门面方式单数据查询
find() 只返回1条数据,没有则返回 null,返回的是数组(Array)
Db::name('user')->where('id',1)->find();
value() 获取单数据具体值
Db::name('user')->where('id',1)->value('username');
getBy**() 只查询返回1条,不需要find()
Db::name('user')->getByEmail('oy@qq.com');
getFieldBy**() 只查询返回1条,不需要find(),并且只返回制定的字段
Db::name('user')->getFieldByEmail('oy@qq.com','email');
门面方式多数据查询
select() 返回数据集,没有则返回空数组,返回的是数据集对象(Colletion)
Db::name('user')->select();
field() 指定显示数据列,find同样可用,性能更好
Db::name('user')->field('username,email')->select();
withoutField() 排除指定显示数据列
Db::name('user')->withoutField('username,email')->select();
field() 设置别名
Db::name('user')->field('username as user,gender as sax')->select();
group() 搭配 field() 获取某字段所有不通数值,等于去重
Db::name('user')->field('username')->group('username')->select();
limit() 限制显示条数
Db::name('user')->limit(3)->select();
page() 页数显示 第一个参数是第几页,第二个参数是显示几个
Db::name('user')->page(1,5)->select();
order() 排序顺序 asc正序(默认) desc倒序
Db::name('user')->order('id','asc')->select();
直接转换成数组
Db::name('user')->select()->toArray();
column() 获取具体值的指定列多数据,第二个参数可设置为索引一般用id
Db::name('user')->column('username');
Db::name('user')->column('username','id');
whereColumn() 两个数据对比查询
Db::name('user')->whereColumn('update_time','>','create_time')->select();
where**() 查找某个字段的值 **部分是数据表中字段的名称
Db::name('user')->whereUsername('oy')->select();
Db::name('user')->whereEmail('oy@qq.com')->select();
优化门面方式多数据查询
chunk() 每次读取指定数量数据,大数据量效果明显,节约内存开销
Db::name('user')->chunk(3,function($users){
foreach ($users as $user) {
dump($user);
}
});
cursor() 每次只读取一条,大数据量效果明显,节约内存开销
$cursor = Db::name('user')->cursor();
foreach ($cursor as $user) {
dump($user);
}
链式查询
优化查询
每次使用 Db 都会创建一个实例,如果多次使用,可以把对象保存下来。 此外,同一个对象实例第二次查询会保留第一次的数值,如要清空第一次的值,请使用 removeOption('where')
$userQuery = Db::name('user');
$userFind = $userQuery->where('id',1)->find();
$userSelect = $userQuery->removeOption('where')->select();
门面方式数据库新增
insert() 添加一条数据,返回值是添加的数据数量
$data = [
'username'=>'OY',
'email'=>'oy@qq.com',
'gender'=>'男',
'price'=>'100',
'details'=>'123',
];
Db::name('user')->insert($data);
field() 限制可新增的字段,不在范围内的字段添加会报错并添加失败
Db::name('user')->field('username,email,gender,price,details')->insert($data);
如果添加不存在字段,无视报错强制插入,使用 strict(false)
Db::name('user')->strict(false)->insert($data);
replace() insert表中存在相同主键会报错,replace则会修改
Db::name('user')->replace()->insert($data);
insertGetId() 新增数据后返回新增数据的主键id值
Db::name('user')->insertGetId($data);
insertAll() 批量添加多条数据,返回值是添加的数据数量
$data = [
[...],
[...],
[...],
];
Db::name('user')->insertAll($data);
save()通用方法
- 不存在主键则新增
- 存在主键则修改
- 门面方式没有saveAll(),只有模型才有saveAll()
Db::name('user')->save($data);
修改数据
update() 需要指向主键,成功返回修改的行数,数据相同则返回0
$data = [
'id'=>1,
'username'=>'OY',
];
return Db::name('user')->update($data);
或者使用 where()
$data = [
'username'=>'OY',
];
return Db::name('user')->where('id',1)->update($data);
如果要更新的数据需要使用SQL函数,使用exp()
$data = [
'username'=>'OY923',
];
return Db::name('user')->where('id',1)
->exp('email','UPPER(email)')
->update($data);
自增和自减
return Db::name('user')->where('id',1)
->inc('price')
->dec('details')
->update($data);
raw 兼容以上2种方法,可读性更高
$data = [
'id'=>1,
'email'=>Db::raw('UPPER(email)'),
'price'=>Db::raw('price+1'),
'details'=>Db::raw('details-1'),
];
门面方式删除数据
delete() 通过主键删除数据,成功返回删除的行数,没有找到删除的数据则返回0
Db::name('user')->delete(1);
Db::name('user')->where('id',1)->delete();
删除多条数据
Db::name('user')->delete([1,2,3]);
门面方式数据库查询
比较查询,where 如果是 = 可以省略,<> 是不等于
Db::name('user')->where('id','=',6)->find();
Db::name('user')->where('id',6)->find();
Db::name('user')->where('id','>',6)->select();
Db::name('user')->where('id','<>',6)->select();
区间查询,like 模糊查询,link 多条件下默认是 and
Db::name('user')->where('email','like','oy%')->select();
Db::name('user')->where('email','like',['oy%','tb%'])->select();
Db::name('user')->where('email','like',['oy%','tb%'],'or')->select();
Db::name('user')->whereLike('email','oy%')->select();
Db::name('user')->whereNotLike('email','oy%')->select();
Db::name('user')->whereOr([
['email','like','oy%'],
['email','like','oldyellow%']
])->select();
区间查询,between 字符串和数组模式都可以
Db::name('user')->where('id','between','2,10')->select();
Db::name('user')->where('id','between',[2,10])->select();
Db::name('user')->whereBetween('id',[2,10])->select();
Db::name('user')->whereNotBetween('id',[2,10])->select();
区间查询,in 指定数据,字符串和数组模式都可以
Db::name('user')->where('id','in','5,10,12')->select();
Db::name('user')->where('id','in',[5,10,12])->select();
Db::name('user')->whereIn('id',[5,10,12])->select();
Db::name('user')->whereNotIn('id',[5,10,12])->select();
区间查询,null
Db::name('user')->where('uid','null')->select();
Db::name('user')->where('uid','not null')->select();
Db::name('user')->whereNull('uid')->select();
Db::name('user')->whereNotNull('uid')->select();
EXP查询 SQL语法自定义查询
Db::name('user')->where('id','exp','IN(5,10,12)')->select();
whereRaw 条件部分直接使用 SQL 语句查询
Db::name('user')
->whereRaw('SQL语句')
->select();
门面方式数据库时间查询
比较查询,where 如果是 = 可以省略
Db::name('user')->where('create_time','=','2020-1-20')->select();
Db::name('user')->where('create_time','2020-1-20')->select();
多条件查询
Db::name('user')->where([
['username','=','OY9'],
['price','>','100'],
])->select();
区间查询,between 其中 whereTime 可省略 > , whereBetweenTime 是数组变字符串方式
Db::name('user')->where('create_time','>','2020-1-20')->select();
Db::name('user')->whereTime('create_time','>','2020-1-20')->select();
Db::name('user')->where('create_time','between',['2020-1-20','2020-1-21'])->select();
Db::name('user')->whereBetween('create_time',['2020-1-20','2020-1-21'])->select();
Db::name('user')->whereNotBetween('create_time',['2020-1-20','2020-1-21'])->select();
Db::name('user')->whereBetweenTime('create_time','2020-1-20','2020-1-21')->select();
固定查询 whereYear whereMonth whereDay
Db::name('user')->whereYear('create_time')->select();
Db::name('user')->whereYear('create_time','last year')->select();
Db::name('user')->whereYear('create_time','2016')->select();
Db::name('user')->whereMonth('create_time')->select();
Db::name('user')->whereMonth('create_time','last month')->select();
Db::name('user')->whereMonth('create_time','2016-6')->select();
Db::name('user')->whereDay('create_time')->select();
Db::name('user')->whereDay('create_time','last day')->select();
Db::name('user')->whereDay('create_time','2016-6-6')->select();
有效期查询 whereBetweenTimeField()
Db::name('user')->whereBetweenTimeField('start_time','end_time')->select();
门面方式数据库聚合查询
count 数据总条数
$data = Db::name('user')->count();
max 最大值
$data = Db::name('user')->max('price');
min 最小值
$data = Db::name('user')->min('price');
avg 平均值
$data = Db::name('user')->avg('price');
sum 总和
$data = Db::name('user')->sum('price');
门面方式数据库子查询
数据分成多个表存放,子表通过 uid 和主表 id 连接 buildSql() 返回的是SQL子查询语句
$subQuery = Db::name('marry')->field('uid')->where('marry',1)->buildSql();
$result = Db::name('user')->where('id','exp','IN '.$subQuery)->select();
也可以用闭包,这里不需要再写 buildSql()
$result = Db::name('user')->where('id','in',function($query){
$query->name('marry')->field('uid')->where('marry',1);
})->select();
门面方式数据库原生SQL语句查询
query() 适合读取
Db::query();
execute() 适合更新和写入
Db::execute();
门面方式判断运行数据库语句
when() 通过第一个参数判断,类似if条件语句
Db::name('user')->when(true,function($query){
$query->where('username',1);
},function($query){
$query->where('username',2);
})->select();
事务处理
数据库表的存储引擎,必须是 InnoDB。 简单理解就是,2件事情,前者失败,后者即使成功也回滚。 或者前者成功,后者失败,前者也回滚。 只能对错误表或者字段实现。
自动
Db::transaction(function () {
Db::name('user1')->where('id',1)->save(['price'=>Db::raw('price+1')]);
Db::name('user')->where('id',7)->save(['price'=>Db::raw('price+1')]);
});
手动,可自定义报错后的处理
Db::startTrans();
try {
Db::name('user1')->where('id',1)->save(['price'=>Db::raw('price+1')]);
Db::name('user')->where('id',7)->save(['price'=>Db::raw('price+1')]);
// 提交事务
Db::commit();
} catch (\Exception $e) {
echo '失败';
// 回滚事务
Db::rollback();
}
门面方式获取器
withAttr() 对获取的数据2次处理,然后return再输出。
$data = Db::name('user')->withAttr('email',function($value,$data){
return strtoupper($value);
})->select();
dump($data);
门面方式数据集
$data = Db::name('user')->select();
dump($data->toArray());
$data = Db::name('user')->select();
dump($data->shuffle());
$data = Db::name('user')->select();
dump($data->whereIn('id',[5,8,10]));
模型连接据库
创建 app/model/User.php
<?php
namespace app\model;
use think\Model;
class User extends Model
{
}
模型在控制器中使用
use app\model\User as UserModel;
UserModel::select();
模型初始化
class User extends Model
{
protected static function init()
{
echo '初始化';
}
}
模型新增
save() 模型新增必须要实例化,门面方式不需要。返回添加数量。
$data = [
'username'=>'OY5',
'email'=>'oy@qq.com',
'gender'=>'男',
'price'=>'100',
'details'=>'123',
];
$user = new UserModel();
$result = $user->save($data);
获取插入数据的id,只有save方法有。
$user->id;
此外发现,模型的insert()新增,无需实例化,为啥这就可以不需要实例化?
UserModel::insert($data);
allowField() 允许写入字段,参数为数组格式。
$user->allowField(['username'])->save($data);
saveAll() 批量新增数据,同样需要实例化,返回的是添加数据的数组。
$data = [
[...],
[...],
[...],
];
$user = new UserModel();
result = $user->saveAll($data);
create() 静态方法,无需实例化,TP6新增的官方推荐使用。
$data = [
'username'=>'OY5',
'email'=>'oy@qq.com',
'gender'=>'男',
'price'=>'100',
'details'=>'123',
];
$result = UserModel::create($data,['username','email','gender'],false);
echo $result->id;
模型删除
delelt() 返回布尔值,不存在返回会报错?
UserModel::find(50)->delete();
UserModel::find([47,48,49])->delete();
destroy() 支持单个和批量删除,无论成功与否返回的都是 true,不存在返回会报错?
UserModel::destroy(1);
UserModel::destroy([2,5,6]);
模型修改数据
通过 find() 找到需要删除的对象
$data = [
'username'=>'OY'
];
$user = UserModel::find(6)->save($data);
通过 where() 找到需要删除的对象
$data = [
'username'=>'OY'
];
$user = UserModel::where('id',6)->save($data);
allowField() 允许更新数据。
UserModel::find(6)->allowField(['username'])->save($data);
saveAll() 批量性修改,必须有id,必须实例化。 save系列的貌似都需要实例化。
$user = new UserModel();
$list = [
[
'id'=>'6',
'username'=>'OY5abcd'
],
[
'id'=>'7',
'username'=>'OY5abcd'
]
];
$result = $user->saveAll($list);
update() 静态方法更新,必须要有id
$data = [
'id'=>'6',
'username'=>'OY5abc'
];
$result = UserModel::update($data);
第二个参数是id,第三个参数是允许修改字段。
$data = [
'username'=>'OY5aa',
'email'=>'OY5@qq.com'
];
$user = UserModel::update($data,['id'=>6],['username']);
模型数据查询
几乎和门面方式数据查询一模一样,不全部举例了。 find()
$user = UserModel::find(6);
echo $user->username;
echo $user->create_time;
findOrEmpty()
$user = UserModel::findOrEmpty(1);
if($user->isEmpty()){
echo '空';
}else{
echo $user;
}
select()
UserModel::select([6,9,12]);
模型端处理好,交给控制器直接调用 官方建议使用 getAttr()
class User extends Model
{
public function getUsername()
{
$obj = $this->find(6);
// return $obj->username;
return $obj->getAttr('username');
}
}
控制器端调用
$user = new UserModel();
echo $user->getUsername();
模型获取器
get**Attr() 在模型中输出处理后的数据。
public function getStatusAttr($value)
{
$status = [
0=>'零',
1=>'一',
2=>'二',
3=>'三',
];
return $status[$value];
}
控制器直接输出的是处理过的数据。
$user = UserModel::find(6);
echo $user->status;
getData() 获取指定原始数据
$user = UserModel::find(6);
echo $user->getData('status');
不填参数,就是获取全部原始数据数据
$user->getData();
模型修改器
用于新增、修改数据
public function setEmailAttr($value)
{
return strtoupper($value);
}
模型查询范围
scope**() 在模型中封装好最最常用的SQL语句在控制器中直接使用,可叠加使用
public function scopeGender($query)
{
$query->where('gender','男')
->limit(5);
}
scope() 在控制器中使用,参数是模型里命名函数scope之后部分的名字
UserModel::scope('gender')->select();
带参数查询
public function scopeEmail($query,$value)
{
$query->where('email','like','%'.$value.'%');
}
在控制器中使用
UserModel::scope('email','lihei@qq.com')->select();
强制全局查询条件,可多个
protected $globalScope =['status'];
public function scopeStatus($query)
{
$query->where('status',1);
}
在控制器里解除强制
UserModel::withoutGlobalScope()->select();
search**Attr() 搜索器,参数必须是数组格式。基本和 scope() 用法一致,当然也可以叠加使用。
$result = UserModel::withSearch(['email'],[
'email' => 'oy'
])->select();
模型数据集
基本和门面方式一样,都是对已近取得的结果集进行处理。 www.kancloud.cn/manual/thin…
hidden() 模型独有
$data = UserModel::select();
dump($data->hidden(['username','email']));
visible() 模型独有
$data = UserModel::select();
dump($data->visible(['username','email']));
自动时间戳
database.php 默认开启,新增数据 create_time update_time 自动添加时间。
模型只读字段
修改时无法修改数据库字段,只对 save() 方法有效,update() 无效。 在模型中设置
protected $readonly =['email'];
在控制器中设置
$data = [
'username'=>'OY',
'email'=>'OY@qq.com'
];
UserModel::find(6)->readonly(['email'])->save($data);
模型数据类型转换
在模型中对数据类型进行转换 www.kancloud.cn/manual/thin…
protected $type = [
'price' => 'float',
'create_time' => 'datetime:Y-m-d',
];
var_dump() 可现实数据类型
模型废弃字段
在模型中设置后将不能使用这些字段
protected $disuse = [’status‘,’uid‘];
门面方式JSON
mysql5.7+的版本已经内部支持json格式 save() insert() 新增
$data = [
'username'=>'OY',
'email'=>'oy@qq.com',
'gender'=>'男',
'price'=>'100',
'details'=>'123',
'list'=>['username'=>'OY','email'=>'oy@qq.com'],
];
Db::name('user')->json(['list'])->save($data);
find() select() 查询
Db::name('user')->json(['list'])->find(6);
条件查询(必须mysql5.7)
Db::name('user')->json(['list'])->where('list->username','oy')->select();
update() save() 更新(必须mysql5.7)
$data['list->username'] = 'OY';
Db::name('user')->json(['list'])->where('id',58)->update($data);
模型JSON
在模型中设置好就可以了
protected $json = ['list'];
新增
$data = [
'username'=>'OY',
'email'=>'oy@qq.com',
'gender'=>'男',
'price'=>'100',
'details'=>'123',
'list'=>['username'=>'OY','email'=>'oy@qq.com'],
];
$user = new UserModel();
$result = $user->save($data);
查询
UserModel::find(58);
UserModel::select();
条件查询(必须mysql5.7)
UserModel::where('list->username','OY')->select();
更新(必须mysql5.7)
$data['list->username'] = 'OY';
UserModel::where('id',58)->update($data);
模型软删除
模型开启软删除,数据库有 delete_time 字段,必须默认为 NULL
use think\model\concern\SoftDelete;
user SoftDelete;
显示包含软删除数据
UserModel::withTrashed()->select();
只显示包含软删除数据
UserModel::OnlyTrashed()->select();
恢复软删除数据
$result = UserModel::onlyTrashed()->find(58);
$result->restore();
destroy() 硬删除,需要先还原再删除
$result = UserModel::onlyTrashed()->find(58);
$result->restore();
UserModel::destroy(58,true);
delete() 硬删除
UserModel::onlyTrashed()->find(58)->force()->delete();
门面方式查询事件
public function initialize(){
Db::event('before_select', function ($query) {
echo 'before_select';
});
}
模型查询事件
写在模型里 www.kancloud.cn/manual/thin… onBeforeInsert() 和 onAfterInsert 只有使用 save() 才有效,insert() 无效。
public static function onAfterRead($query)
{
echo 'after_read';
}
public static function onBeforeInsert($query)
{
echo 'before_insert';
}
public static function onAfterInsert($query)
{
echo 'after_insert';
}
关联模型
表与表之间实现关联 www.kancloud.cn/manual/thin…
关联模型一对一
hasOne() 主 user 表和被关联 profile 数据表一对一
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
控制器
$result = UserModel::find(1);
$result->profile;
belongsTo() 反向一对一
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
修改关联表数据
$user = UserModel::find(2);
$data = [
'love'=>'gaming',
];
$result = $user->profile->save($data);
新增关联表数据 profile 改成 profile() 即是新增
$result = $user->profile()->save($data);
关联模型一对多
hasMany() 主 user 表和被关联 profile 数据表一对多
class User extends Model
{
public function profile()
{
return $this->hasMany(Profile::class);
}
}
控制器 2种方法
$result = UserModel::find(1);
$result->profile;
$result->profile()->select();
saveAll() 添加多条关联数据
$user = UserModel::find(1);
$data = [
['love'=>'gaming1',],
['love'=>'gaming2',]
];
$user->profile()->saveAll($data);
删除主表的同时删除附表数据,支持软删除
$user = UserModel::with('profile')->find(4);
$user->together(['profile'])->delete();
with() 多数据获取
$result = UserModel::with(['profile'])->select([1,2,3]);
return json($result);
读取
$result = UserModel::with(['profile'])->select([1,2,3]);
foreach($result as $user){
echo $user->profile;
}
一对多表数据
$result = UserModel::with(['profile','book'])->select([1,2,3]);
foreach($result as $user){
echo $user->profile.$user->book;
}
withCount() 关联统计,获取字表关联的数量 获取方法是 表名_count
$result = UserModel::withCount(['book'])->select([1,2,3]);
foreach($result as $user){
echo $user->book_count;
echo '<br>';
}
关联模型多对多
一般用于用户多权限
表user:用户
表role:权限
表access:真正存储用户和权限管理的数据
Access表设置关联
use think\model\Pivot;
class Access extends Pivot
{
}
查询用户id=1的role数据
$user = UserModel::find(1);
eturn $user->roles;
为id=1的用户,添加role的3权限数据
$user = UserModel::find(1);
$user->roles()->save(Role::find(3));
删除id=1的用户,删除role的3权限数据
$user = UserModel::find(1);
$user->roles()->detach(Role::find(3));
路由
控制器
class Address
{
public function details($id = null)
{
return $id;
}
}
路由
Route::rule('ad/:id', 'Address/details');
原生访问地址
127.0.0.1:8000/address/details/id/1
路由访问地址
127.0.0.1:8000/ad/1
强制参数只能是数字
Route::rule('ad/:id', 'Address/details')->pattern(['id'=>'\d+']);
多参数
Route::rule('ad/:id/:uid', 'Address/details')->pattern(['id'=>'\d+','uid'=>'\d+']);
原生访问地址
127.0.0.1:8000/address/details/id/1/uid/2
路由访问地址
127.0.0.1:8000/ad/1/2
全局 id 和 uid 强制数字
Route::pattern(['id'=>'\d+','uid'=>'\d+']);
路由闭包
Route::get('think/:name', function ($name=null) {
return 'hello,'.$name;
});
未完待续