数据库模型操作

数据库操作

数据库配置

配置文件路径:application\database.php ,里面设置了应用的全局数据库配置信息

return [
    // 数据库类型
    'type'        => 'mysql',
    // 服务器地址
    'hostname'    => '127.0.0.1',
    // 数据库名
    'database'    => 'test',
    // 数据库用户名
    'username'    => 'root',
    // 数据库密码
    'password'    => '',
    // 数据库连接端口
    'hostport'    => '',
    // 数据库连接参数
    'params'      => [],
    // 数据库编码默认采用utf8
    'charset'     => 'utf8',
    // 数据库表前缀
    'prefix'      => '',
    // 数据库调试模式
    'debug'       => true,
];

查询构造器

可以更方便执行数据库操作,查询构造器基于PDO实现,对不同的数据库驱动都是统一的语法

<?php
namespace app\home\controller;

use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;

class Index extends Controller
{
    // 查询数据
    public function index()
    {
        // 查询admin表的所有数据,注意table方法必须指定完整的数据表名
        $UserData = Db::table('pre_user')->select();

        // ThinkPHP提供调试函数,如果需要打印结果可以使用该函数
        halt($UserData);

        // 如果设置了数据表前缀参数的话,可以使用
        Db::name('user')->select();

        // 查询id为1的单条数据
        Db::name('user')->where('id',1)->find();

        // 查询status字段等于1的所有数据
        Db::name('user')->where('status',1)->select();

        // 查询某个字段的值
        Db::name('user')->where('id',1)->value('name');

        // 查询某一列的值
        Db::name('user')->where('status',1)->column('name');

        // 查询某一列的值并且指定索引
        Db::name('user')->where('status',1)->column('name','id');
    }

    // 添加数据
    public function add()
    {
        // insert方法
        $data = ['foo' => 'bar', 'bar' => 'foo'];
        Db::name('user')->insert($data);

        // 返回自增主键 getLastInsID方法以及insertGetId方法
        Db::name('user')->insert($data);
        $userId = Db::name('user')->getLastInsID();

        Db::name('user')->insertGetId($data);

        // 添加多条数据
        $data = [
            ['foo' => 'bar', 'bar' => 'foo'],
            ['foo' => 'bar1', 'bar' => 'foo1'],
            ['foo' => 'bar2', 'bar' => 'foo2']
        ];

        Db::name('user')->insertAll($data);
    }

    // 编辑数据
    public function edit()
    {
        // update => 更新数据 where => 条件 要注意的是更新数据必须要有条件
        Db::name('user')->where('id', 1)->update(['name' => 'thinkphp']);

        // 如果数据中包含主键,可以直接使用
        Db::name('user')->update(['name' => 'thinkphp','id'=>1]);
    }

    // 删除数据
    public function del()
    {
        // 根据主键删除
        Db::name('user')->delete(1);
        Db::name('user')->delete([1,2,3]);

        // 条件删除    
        Db::name('user')->where('id',1)->delete();
        Db::name('user')->where('id','<',10)->delete();
    }
}

查询表达式

查询表达式支持大部分的SQL查询语法,也是 ThinkPHP 查询语言的精髓,查询表达式的使用格式

where('字段名','表达式','查询条件');
whereOr('字段名','表达式','查询条件');

表达式不分大小写,支持的查询表达式有下面几种,分别表示的含义是:

表达式 含义
EQ、= 等于(=)
NEQ、<> 不等于(<>)
GT、> 大于(>)
EGT、>= 大于等于(>=)
LT、< 小于(<)
ELT、<= 小于等于(<=)
LIKE 模糊查询
[NOT] BETWEEN (不在)区间查询
[NOT] IN (不在)IN 查询
[NOT] NULL 查询字段是否(不)是NULL
[NOT] EXISTS EXISTS查询
EXP 表达式查询,支持SQL语法
> time 时间比较
< time 时间比较
between time 时间比较
notbetween time 时间比较
<?php
namespace app\home\controller;

use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;

class Index extends Controller
{
    // 查询数据
    public function index()
    {
        // 查询用户表id等于100的单条数据 下面的操作等效于where('id',100)
        Db::name('user')->where('id','eq',100)->find();
        Db::name('user')->where('id','=',100)->find();

        // 查询用户表id不等于100的数据
        Db::name('user')->where('id','neq',100)->select();
        Db::name('user')->where('id','<>',100)->select();

        // 模糊查询name带有thinkphp的数据
        Db::name('user')->where('name','like','%thinkphp%')->select();

        // 查询id在1到8区间的数据 同时支持数组的写法
        Db::name('user')->where('id','between',[1,8])->select();
        Db::name('user')->where(['id'=> ['between',[1,8]]])->select();

        // 数组写法
        Db::name('user')->where(['id'=> ['between',[1,8]],'status' => ['=',1]])->select();

        // exp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称
        Db::name('user')->where('id','exp',' IN (1,3,8) ')->select();
    }
}

链式操作

支持链式操作的查询方法包括

方法名 描述
alias 设置表别名
field 查询字段
limit 指定查询多条数据
order 排序
group 根据一个或多个列对结果集进行分组
join 根据两个或多个表中的列之间的关系
fetchSql 直接返回SQL而不是执行查询
<?php
namespace app\home\controller;

use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;

class Index extends Controller
{
    // 查询数据
    public function index()
    {
        // 链表查询
        // INNER JOIN: 等同于 JOIN(默认的JOIN类型),如果表中有至少一个匹配,则返回行
        // LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
        // RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
        Db::table('think_user')
            ->alias('a')
            ->join('think_dept b ','b.user_id= a.id')
            ->select();

        Db::table('think_user')
            ->alias('a')
            ->join('think_dept b ','b.user_id= a.id')
            ->select();

        // 按照用户id进行分组统计
        Db::table('user')
            ->field('user_id,username,max(score)')
            ->group('user_id')
            ->select();

        // 查询5个满足条件的数据 并按照id倒序排列
        Db::table('user')
            ->where('status', 1)
            ->field('id,name')
            ->order('id', 'desc')
            ->limit(5)
            ->select();
    }
}

聚合查询

经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等

方法 说明
count 统计数量,参数是要统计的字段名(可选)
max 获取最大值,参数是要统计的字段名(必须)
min 获取最小值,参数是要统计的字段名(必须)
avg 获取平均值,参数是要统计的字段名(必须)
sum 获取总分,参数是要统计的字段名(必须)
<?php
namespace app\home\controller;

use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;

class Index extends Controller
{
    public function index()
    {
        // 获取用户数
        Db::table('think_user')->count();

        // 获取用户的最大积分
        Db::table('think_user')->max('score');
    }
}

事务操作

最简单的方式是使用transaction方法操作数据库事务,当闭包中的代码发生异常会自动回滚

// 写入失败的话,系统会自动回滚,写入成功的话系统会自动提交当前事务
Db::transaction(function () {
    Db::table('think_user')->find(1);
    Db::table('think_user')->delete(1);
});

也可以手动控制事务

// 启动事务
Db::startTrans();
try {
    Db::table('think_user')->find(1);
    Db::table('think_user')->delete(1);
    // 提交事务
    Db::commit();
} catch (\Exception $e) {
    // 回滚事务
    Db::rollback();
}

模型

模型类通常完成实际的业务逻辑和数据封装,并返回和格式无关的数据

定义模型

<?php

namespace app\common\model\Business;

// 引入TP基础模型
use think\Model;
// 引入软删除模型 对数据频繁使用删除操作会导致性能问题,软删除的作用就是把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢复
use traits\model\SoftDelete;

// 继承TP基础模型 注意:模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写
class Business extends Model
{
    // 使用软删除模型
    use SoftDelete;

    // 设置当前模型对应的完整数据表名称(如果你的命名规则和上面的系统约定不符合时才需要设置该属性)
    protected $table = 'pre_business';

    // 开启自动写入时间戳字段 默认时间类型是int,如果是datetime的,那么需要把true改为datetime
    protected $autoWriteTimestamp = true;

    // 定义时间戳字段名 默认创建时间字段为create_time,更新时间字段为update_time
    protected $createTime = 'createtime';

    //  如果不需要更新时间把该属性设置为false
    protected $updateTime = false;

    // 定义软删除字段(标识符)
    protected $deleteTime = 'deletetime';

    // 追加数据表不存在的字段
    protected $append = [
        'gender_text'
    ];

    /**
     * 定义数据表中不存在的字段的获取器  以get不存在的字段名Attr该规则命名方法名(根据业务需求)
     * @param $value 当前字段的值
     * @param $data 当前的所有数据数组
    */
    public function getGenderTextAttr($value,$data)
    {
        $gender = !empty($data['gender']) ? $data['gender'] : 0;

        $genderList = [0 => '保密',1 => '男',2 => '女'];

        return $genderList[$gender];
    }

    /**
     * 定义数据表中存在的字段的获取器 以get字段名 (根据业务需求)
     * @param $value 当前字段的值
    */
    public function getDealAttr($value)
    {
        $dealList = [0 => '未成交',1 => '已成交'];

        return $dealList[$value];
    }

    // 关联查询(根据业务需求)
    public function address()
    {
        /* 
            belongsTo 相应关联查询
                第一个参数 model => 需要关联模型
                第二个参数 foreignKey => 外键
                第三个参数 locaKey => 主键
                第四个参数 alias => 模型别名
                第五个参数 joinType => 链表查询(LEFT,INNER,RIGHT)

            setEagerlyType 设置预载入方法
                0 => JOIN查询
                1 => IN查询
        */
        return $this->belongsTo('app\common\model\Business\Address','busid','id',[],'LEFT')->setEagerlyType(0);
    }   
}

模型数据操作

Db 类一样对数据库进行增删改查

<?php
namespace app\home\controller;

use think\Controller;
// 引入User模型
use app\common\model\User;

class Index extends Controller
{
    // 定义属性
    protected $UserModel = null; 

    // 控制器初始化
    public function _initialize()
    {
        // 实例化模型再赋值给this 第一种写法
        // $this->UserModel = new User();

        // 第二种写法
        $this->UserModel = model('User');

        // 如果用助手调用多级模型 例如:路径:app\common\model\User\User
        // $this->UserModel = model('User.User');
    }

    // 查询数据
    public function index()
    {
        // 查询用户表的所有数据
        $UserData = $this->UserModel->select();

        // 查询用户表里的status为1的所有数据
        $UserData = $this->UserModel->where(['status' => 1])->select();

        // 查询单条数据 1 代表主键
        $UserData = $this->UserModel->find(1);
        $UserData = $this->UserModel->where(['name' => 'thinkPHP'])->find();

        // 链式操作
        $UserData = $this->UserModel->where(['status' => 1])->order('createtime DESC')->limit(10)->select();
    }

    // 添加数据
    public function add()
    {
        // 第一种写法
        $data = [
            'username' => 'thinkPHP',
            'status' => 1
        ];

        $result = $this->UserModel->save($data);

        // 第二种写法
        $this->UserModel->username = 'demo';

        $this->UserModel->status = 'normal';

        $result = $this->UserModel->save();

        // 获取自增ID
        $userid = $this->UserModel->id;

        // 批量新增
        $data = [
            ['username'=>'thinkphp','email'=>'thinkphp@qq.com'],
            ['username'=>'onethink','email'=>'onethink@qq.com']
        ];

        $result = $this->UserModel->saveAll($data);

    }

    // 编辑数据
    public function edit()
    {
        // 需要修改的记录id
        $userid = 6;

        // 第一种写法 先查询再修改
        $User = $this->UserModel->find($userid);

        $User->nickname = 'onethink';
        $User->mobile = 13023562356;

        $result = $User->save();

        // 第二种写法 如果更新数据里有主键就会作为更新条件
        $data = [
            'id' => $userid,
            'nickname' => 'OneThink',
            'mobile' => 13023568956
        ];

        // isUpdate => 是否更新数据
        $result = $this->UserModel->isUpdate(true)->save($data);

        // 批量更新
        $data = [
            ['id' => 5,'username'=>'ThinkPHP','email'=>'ThinkPHP@qq.com'],
            ['id' => 6,'username'=>'oneThink','email'=>'oneThink@qq.com']
        ];

        $result = $this->UserModel->saveAll($data);
    }

    // 删除数据
    public function del()
    {
        // 需要删除的记录id
        $userid = 5;

        // 第一种写法 先查询再删除
        $User = $this->UserModel->find($userid);

        $User->delete();

        // 第二种写法 destroy => 支持数组 [1,2,3] 
        $result = $this->UserModel->destroy($userid);
    }
}

软删除

在实际项目中,对数据频繁使用删除操作会导致性能问题,软删除的作用就是把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢复

用法示例

首先在需要使用软删除的模型定义以下内容:

<?php

namespace app\common\model\Business;

// 引入TP基础模型
use think\Model;
// 引入软删除模型
use traits\model\SoftDelete;

// 继承TP基础模型
class Business extends Model
{
    // 使用软删除模型
    use SoftDelete;

    // 设置数据表
    protected $table = 'pre_business';

    // 开启自动写入时间戳
    protected $autoWriteTimestamp = true;

    // 自定义创建时间字段
    protected $createTime = 'createtime';

    // 自定义更新时间字段
    protected $updateTime = false;

    // 定义软删除时间字段(标识符)
    protected $deleteTime = 'deletetime';
}

然后在控制器调用

<?php
namespace app\home\controller;

use think\Controller;

class Index extends Controller
{
    // 定义属性
    protected $UserModel = null; 

    // 控制器初始化
    public function _initialize()
    {
        // 实例化模型
        $this->UserModel = model('User');
    }

    // 查询数据
    public function index()
    {
        // 默认情况下查询的数据不包含软删除数据,如果需要包含软删除的数据,可以使用下面的方式查询
        $data = $this->UserModel->withTrashed()->find();
        $data = $this->UserModel->withTrashed()->select();

        // 如果仅仅需要查询软删除的数据,可以使用
        $data = $this->UserModel->onlyTrashed()->find();
        $data = $this->UserModel->onlyTrashed()->select();
    }

    // 软删除操作
    public function del()
    {
        // 需要删除的记录id
        $userid = 5;

        // 第一种写法 先查询再软删除
        $User = $this->UserModel->find($userid);

        $User->delete();

        // 真实删除
        $User->delete(true);

        // 第二种写法 destroy => 支持数组 [1,2,3] 
        $result = $this->UserModel->destroy($userid);

        // 真实删除
        $result = $this->UserModel->destroy($userid,true);
    }
}

验证器

ThinkPHP5.0验证使用独立的\think\Validate类或者验证器进行验证

定义验证器

路径:app\common\validate 里面都是放验证器,如果 validate 文件夹不存在的话,请手动创建

<?php

namespace app\common\validate\Business;

// 引入tp的验证器
use think\Validate;

// 客户验证器
class Business extends Validate
{
    // 验证规则
    protected $rule = [
        /* 
            require => 字段必填
            regex => 正则验证
            unique => 验证字段值是否为唯一的 支持指定完整模型类 并且默认会优先检测模型类是否存在 不存在则检测数据表
        */
        'mobile' => ['require','regex:/^1[3456789]{1}\d{9}$/','unique:business'],
        'nickname' => ['require'],
        'password' => ['require']

    ];

    // 错误提示信息
    protected $message = [
        'mobile.require' => '手机号必填',
        'mobile.regex' => '手机号格式错误',
        'mobile.unique' => '手机号已注册',
        'nickname.require' => '密码必填',
        'password.require' => '密码必填',
    ];

    // 验证场景
    protected $scene = [
        // 注册用户的验证场景
        'add' => ['mobile','password'],
        // 用户编辑资料的场景
        'edit' => ['nickname']
    ];
}

点击该地址了解更多内置规则

用法示例

上面已经定义好验证器,接下来看验证器的用法

<?php
namespace app\home\controller;

use think\Controller;

class Index extends Controller
{
    // 定义属性
    protected $BusinessModel = null; 

    // 控制器初始化
    public function _initialize()
    {
        // 实例化模型
        $this->BusinessModel = model('Business.Business');
    }

    // 添加数据
    public function add()
    {
        // 需要添加数据
        $data = [
            'mobile' => 13800000000,
            'password' => 123456
        ];

        // 第一种写法 控制器验证 需要继承TP基础控制器
        $Validate = $this->validate($data,'common/Business/Business');

        // 需要验证场景
        $Validate = $this->validate($data,'common/Business/Business.add');

        if($Validate === FALSE)
        {
            // 提示错误信息
            $this->error($Validate);
        }

        $result = $this->BusinessModel->save($data);

        // 第二种写法 模型验证
        $result = $this->BusinessModel->validate('common/Business/Business')->save();

        // 验证场景
        $result = $this->BusinessModel->validate('common/Business/Business.add')->save($data);

        if($result === FALSE)
        {
            // getError => 返回模型的错误信息
            $this->error($this->BusinessModel->getError());
        }
    }
}
powered by GitbookEdit Time: 2024-06-06 18:25:40