为什么推荐优先使用模型(一)

模型提供一些事件

如果我给所有表都添加了创建者字段(creator)
创建时应该写入该字段
使用模型类添加数据

    # user 模型中重写onBeforeInsert
    # 在插入前添加creator 属性
    public static function onBeforeInsert(Model $model)
    {
        $model->creator = 6;
    }
    
    # 触发事件,插入前添加creator=6
    # 如果要让所有表都添加creator字段
    # 可以写一个公共model类,其继承model,在其中重写 onBeforeInsert
    # 其他模型类继承该类即可
    User::create(['username' => 'username_1', 'password' => 'username_1_password']);

使用db类添加数据

        $time = date('Y-m-d H:i:s');
        # 使用Db类,创建时间和修改时间不会自动写入
        # 使用Db的创建数据,每一个地方都要手动添加creator
        Db::name('user')->save(['username' => 'username_2', 'password' => 'username_2', 'created_at' => $time, 'updated_at' => $time, 'creator' => 6]);
提供修改器和获取器

以user表的电话(mobile)为例
前期功能已经开发好了
后期为了数据安全想对数据库中的数据加密(数据库中存储密文)
如果使用的是DB类,那么用到手机号的地方都要调用解密方法
新增的地方都要调用加密方法
如果使用的是模型可以增加电话获取器(返回解密后结果)
增加电话修改器(返回加密结果)

使用Db类来完成上述新增需求

        # 每个新增的地方都要改
        # $phone 代表电话号码
        $encryptPhone = openssl_encrypt($phone, 'aes-128-cbc', 'xrx', 0, 'abc_efg_hij_klm_');
        Db::name('user')->save([
            'username' => 'username_db',
            'password' => 'password_db',
            'mobile' => $encryptPhone,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);

使用Db类来完成上述查询需求

        $result = Db::name('user')->find(13);
        # 每个用到电话得地方都要增加解密这行
        return openssl_decrypt($result['mobile'], 'aes-128-cbc', 'xrx', 0, 'abc_efg_hij_klm_');

通过修改器完成上述新增需求

    # user模型中 增加mobile修改器
    # 方法名称 = set + 属性名(第一个字母大写) + Attr
    public function setMobileAttr($mobile)
    {
        return openssl_encrypt($mobile, 'aes-128-cbc', 'xrx', 0, 'abc_efg_hij_klm_');
    }
    
    # 新增,就是普通的模型保存
    # $phone 电话号码
        User::create([
            'username' => 'username_attr',
            'password' => 'password_attr',
            'mobile' => $phone,
        ]);

通过修改器完成上述查询需求

    # 增加mobile获取器
    # 方法名称 = get + 属性名(第一个字母大写) + Attr
    public function getMobileAttr($mobile)
    {
        return openssl_decrypt($mobile, 'aes-128-cbc', 'xrx', 0, 'abc_efg_hij_klm_');
    }
    
    # 查询,就是普通模型查询
    $user = User::find(13);
    return $user->mobile;
提供了软删除

模型提供了软删除方法
模型中使用 think\model\concern\SoftDelete 即可
如果使用Db类需要自己手动去标记数据是否删除
查询时where条件需要带上标识字段状态
使用模型则不需要关注这些,调用模型的删除方法和查询方法即可

提供了查询作用域

将一些针对某些特定业务的常用查询封装成作用域
以 user(作者表) user.score(分数) 为例
按照分数分为,青铜,白银,黄金,钻石作者
可以将其封装成作用域,上层调用不需要关心其分数
而且通过该作用域的查询,就算以后分数分组规则改了(只需要在作用域中修改条件即可)

创建白银作者本地作用域

    # 写在user模型中
    # 本地作用域命名规范 scope + 作用域名称
    # 白银作者分数[2000,3000]
    public function scopeAg($query){
        $query->whereBetween('score', [2000, 3000]);
    }

使用作用域查找白银作者

        # 通过scope($scope)
        # $scope 过滤器名称 使用单个过滤器传string
        $users = User::scope(['Ag'])->select();

        # 使用多个过滤器传array
        # 查找满足特定年龄的白银作者
        $users = User::scope(['Ag', 'Age'])->select();

全局作用域
就是设置默认的作用域,不需要像本地作用域一样显式调用
假设你的订单数量到达1000万左右,这是查询比较慢了
这时你的Leader和你说只能查三个月内的
这时就可以通过全局作用域解决这个问题

创建order全局作用域

    # 声明和声明本地作用域一样
    # 这里在 Order模型中声明
    public function ScopeBase($query)
    {
        # 我知道800万条之前的都是大于现在三个月的时间(提高查询速度)
        # 时间应该动态去算,这里就假设今天是2022-04-29,那么三个月前就是2022-01-29
        $query->where('id', '>', 8000000)->where('created_at', '>=', '2022-01-29');
    }

    # 只不过需要将作用域添加到 model globalScope属性之中
    # 这里添加到Order模型 的 globalScope属性之中
    protected $globalScope = ['base'];

全局作用域使用

        # 和普通的模型查询一样
        $order = new Order();
        # SELECT * FROM `order` WHERE `id` > 8000000 AND `created_at` >= '2022-01-29' AND `order_number` = '996_icu' LIMIT 1
        $order->where('order_number', 'hello_world')->find();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值