thinkphp-JSON字段、模型的软删除、模型和数据库的事件
数据库中使用JSON 和模型中使用JSON 的方法
数据库写入JSON 字段,直接通过数组的方式即可完成。比如在控制器中:
$data = [
'username' => '辉夜',
'password' => '123',
...
// 不需要写json字符串 只需要写一个数组就行 系统会自动转换
// 前提是数据表中List字符串的类型是json
'list' => ['username'=>'小红', 'gender'=>'女', 'email' => 'xiaohong@163.com']
];
return Db::name('user')->json(['list'])->save($data);
注意这里必须提交时候指明那个字段是json类型的字段,这样才能进行转换!否则会报错!
但是如果当list是一个json字段时,取出来的时候,会当作字符串类型
{
id: 332,
username: "辉夜",
password: "123",
...
list: "{"email": "xiaohong@163.com", "gender": "女", "username": "小红"}",
...
}
因此也需要添加一个json方法,指明哪个是json格式
$user = Db::name('user')->json(['list'])->find(332);
return json($user);
如果是修改List字段内容:
$data['list'] = [
'username' => '叼元抖',
'gender' => '男',
'email' => 'public@163.com'
];
return Db::name('user')->where('id', 332)->save($data);
这时候会报错:未定义数组下标: 0,意思就是没指定json字段!
return Db::name('user')->where('id', 332)->json(['list'])->save($data);
如果只需要修改list字段中的json的其中的一个属性呢?比如,仅修改list字段中的用户名:
$data['list->username'] = '力黑';
return Db::name('user')->where('id', 332)->json(['list'])->save($data);
如果要将json 字段里的数据作为查询条件,可以通过如下方式实现
$user = Db::name('user')->json(['list')->where('list->username', '辉夜')->find();
模型json
模型中需要先设置数据表中的哪个字段是json类型:
模型中:
protected $json = ['list'];
控制器中执行插入:
$user = UserModel::create(
//参数1 是新增数据数组,必选
[
'username' => '李白3',
'password' => '123',
...
'list' => ['username'=>'辉夜', 'gender'=>'女','email'=>'huiye@163.com']
]
);
如果不用数组方式,也可以通过对象的方式,进行对json 字段的写入操作
$user = new UserModel();
$user->username = '李白';
$user->password = '123';
$user->xxx = '....';
...
// 需要先创建一个单独的空类
$list = new \stdClass;
$list->username = '红红给';
$list->sex = 'nv';
$list->email = '111@163.com';
// 之后再赋值
$user->list = $list;
$user->save();
通过对象调用方式,直接获取json 里面的数据;
$user = UserModel::find(334);
return $user->list->username;
注意,必须提前在模型中设置:
// 设置json字段
protected $json = ['类型为json的字段名称'];
通过json (list中的json中的内容)的数据查询,获取一条数据
id | username | list | password |
---|---|---|---|
1 | 辉夜 | {"sex": "nv", "email": "111@163.com", "username": "红红给"} | 123 |
$user = UserModel::where('list->username', '红红给')->find();
return $user->list->username;
更新修改json 数据,直接通过对象方式:
$user = UserModel::find(334);
$user->list->username = '科比';
$user->save();
注意!模型操作json,一切的前提都需要在模型文件中设置!
// 设置json字段
protected $json = ['类型为json的字段名称'];
模型的软删除
所谓软删除,就是数据并没有真正从数据库中删除,而是通过一个字段,当这个字段有值的时候,就代表了该行数据被标记为删除了,那么查询的时候就排除该行。
id | username | gender | delete_time | create_time |
---|---|---|---|---|
334 | wubin.work | 男 | null | 2024-4-30 |
如上面这个表,其中的delete_time则为软删除的标记字段。
首先,需要在模型端设置软删除的功能,引入SoftDelete,它是trait;
// 开启软删除
use SoftDelete;
// 指定软删除的标记字段名称 可以不指定, 默认为delete_time
protected $deleteTime = 'delete_time';
在控制器中
UserModel::destroy(334);
id | username | gender | delete_time | create_time |
---|---|---|---|---|
334 | wubin.work | 男 | 2024-04-30 11:04:42 | 2024-4-30 |
执行删除后,数据表会如上所示。
delete_time 默认我们设置的是null,如果你想更改这个默认值,可以设置:
protected $defaultSoftDelete = 0;
软删除和方法如下,包括destroy()和delete():
// 第一次执行删除OK,第二次以后执行删除会报错!
UserModel::find(335)->delete();
UserModel::destroy(334); // 这个方法就算数据已经删除了 也不会再报错
默认情况下,开启了软删除功能的查询,模型会自动屏蔽被软删除的数据;
$user = UserModel::select();
return Db::getLastSql();
此时的SQL:SELECT * FROM `tp_user` WHERE `tp_user`.`delete_time` IS NULL
相当于全局添加了一个查询条件。
在开启软删除功能的前提下,依然想要显示出所有数据,则使用withTrashed()方法取消屏蔽软删除的数据;
$user = UserModel::withTrashed()->select();
return json($user);
被软删除的数据,使用常规的find方法是找不到的,只会返回null。如果只想查询被软删除的数据,使用onlyTrashed()方法即可;
$user = UserModel::onlyTrashed()->select();
return json($user);
如果想要让被软删除的数据恢复,则使用restore方法。
// 首先找到被软删除的数据
$user = UserModel::onlyTrashed()->find(334);
// 然后再恢复
$user->restore();
恢复之后,delete_time又会被赋予null值。
如果想让一条软删除的数据真正删除
使用::destory删除:
// 使用destory删除需要先还原 再删除
$user = UserModel::onlyTrashed()->find(335);
$user->restore();
UserModel::destroy(335, true);
注意,真实删除需要在还原后的destory方法中添加第二个参数,true。如果不添加,依然还是软删除。
使用->delete删除:
依然需要先还原,然后使用force()方法:
$user = UserModel::onlyTrashed()->find(334);
$user->force()->delete();
直接找到软删除的数据直接删除,使用链式操作, 类似清空回收站
UserModel::onlyTrashed()->find(333)->force()->delete();
模型和数据库的事件
数据库的事件
当你执行增删改查的时候,可以触发一些事件来执行额外的操作,这些额外的操作事件,可以部署在构造方法里等待激活执行;
数据库事件方法为Db::event('事件名', '执行函数'),具体事件名如下
before_select | select查询前回调 |
---|---|
before_find | find查询前的回调 |
after_insert | insert操作成功后回调 |
after_update | update操作成功后回调 |
after_delete | delete操作成功后回调 |
数据库事件只支持:find、select、update、delete、insert 这几个方法;
在控制器端,事件一般可以写在初始化方法里,方便统一管理;
namespace app\controller;
use app\BaseController;
use think\facade\Db;
class DataTest extends BaseController {
// 写初始化方法需要继承 extends BaseController
public function initialize() {
Db::event('before_select', function($query) {
echo '执行了批量查询';
});
}
public function index() {
$user = Db::table('tp_user')->select();
}
}
这里的如果修改了select为find,那么初始化中对应的方法也要改为before_find,否则会无效。
Db::event('after_update', function($query) {
echo '执行了修改';
});
public function update(){
return Db::name('user')->where('id', '301')
->save([
'username' => '白居易'
]);
}
模型事件
支持的事件类型更加的丰富,具体如下
事件 | 查询后 | 方法名 |
---|---|---|
after_read | 查询后 | onAfterRead |
bfore_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 |
举一个例子,在模型中:
protected static function onAfterRead($query)
{
echo '一条数据被查询';
}
在控制器中
public function index() {
UserModel::find(19);
}
那么在查询的时候,自动就执行了事件的回调方法一次。
如果这里是UserModel::select();
那么就会发现afterRead被执行了好多次,有多少条结果就执行多少次。
在模型中:
protected static function onBeforeUpdate($query)
{
echo '准备修改中...';
}
protected static function onAfterUpdate($query)
{
echo '修改完毕...';
}
在控制器中:
$user = UserModel::find(331);
$user->username = '姚明';
$user->save();
可以发现会根据修改进程,依次执行回调。