thinkphp-JSON字段、模型的软删除、模型和数据库的事件

6284次阅读 205人点赞 作者: WuBin 发布时间: 2024-04-28 11:06:15
扫码到手机查看

数据库中使用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中的内容)的数据查询,获取一条数据

idusernamelistpassword
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的字段名称'];

模型的软删除

所谓软删除,就是数据并没有真正从数据库中删除,而是通过一个字段,当这个字段有值的时候,就代表了该行数据被标记为删除了,那么查询的时候就排除该行。

idusernamegenderdelete_timecreate_time
334wubin.worknull2024-4-30

如上面这个表,其中的delete_time则为软删除的标记字段。

首先,需要在模型端设置软删除的功能,引入SoftDelete,它是trait;

 // 开启软删除
use SoftDelete;
// 指定软删除的标记字段名称 可以不指定, 默认为delete_time 
 protected $deleteTime = 'delete_time';

在控制器中

UserModel::destroy(334);
idusernamegenderdelete_timecreate_time
334wubin.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_selectselect查询前回调
before_findfind查询前的回调
after_insertinsert操作成功后回调
after_updateupdate操作成功后回调
after_deletedelete操作成功后回调

数据库事件只支持: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();

可以发现会根据修改进程,依次执行回调。

点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:thinkphp
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    9603次阅读 623人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    4297次阅读 317人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    14452次阅读 948人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    13497次阅读 491人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    12015次阅读 963人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    16376次阅读 1307人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    15187次阅读 1234人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    29849次阅读 2347人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    25911次阅读 1994人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录