tp5新手手册随笔记(二)

本文详细介绍了ThinkPHP5的数据库操作,包括原生查询、查询构造器的使用,以及模型的对象化操作。内容涵盖redirect方法、数据查询层次、原生查询方法、查询构造器的链式操作、where条件表达式、聚合查询、时间查询、分块查询等。此外,还讲解了模型的输出方法,如输出数组、隐藏属性、指定属性、追加属性,以及如何输出JSON格式数据。

1.

redirect方法默认使用302跳转,如不需要可以使用第二个参数进行301跳转。
$this->redirect('http://thinkphp.cn',301);

302重定向是暂时的重定向,搜索引擎会抓取新的内容而保存旧的网址。由于效劳器前往302代码,搜索引擎以为新的网址只是暂时的。
301重定向是永久的重定向[1]  ,搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址。
2.

数据查询由低到高分三个层次:

  1. 数据库原生查询(SQL查询);
  2. 数据库链式查询(查询构造器);
  3. 模型的对象化查询;

原生查询

  1. 包括queryexecute两个方法,分别用于查询和写入:create,delete,update,select

  2.  更新记录$result = Db::execute('update think_data set name = "framework" where id = 5 ');
    dump($result);
    // 查询数据$result = Db::query('select * from think_data where id = 5');
    dump($result);
  3. query方法返回的结果是一个数据集(数组),如果没有查询到数据则返回空数组;
  4. query方法用于查询,默认情况下返回的是数据集(二维数组),execute方法的返回值是影响的行数。
  5. 为了简化代码,通常的做法是事先在配置文件中定义好多个数据库的连接配置,例如,我们在应用配置文件(application/config.php)中添加配置如下:

    // 数据库配置1'db1'   =>  [
        // 数据库类型'type'     => 'mysql',
        // 服务器地址'hostname' => '127.0.0.1',
        // 数据库名'database' => 'thinkphp',
        // 数据库用户名'username' => 'root',
        // 数据库密码'password' => '123456',
        // 数据库连接端口'hostport' => '',
        // 数据库连接参数'params'   => [],
        // 数据库编码默认采用utf8'charset'  => 'utf8',
        // 数据库表前缀'prefix'   => 'think_',
    ],
    // 数据库配置2'db2'   =>  [
        // 数据库类型'type'     => 'mysql',
        // 服务器地址'hostname' => '127.0.0.1',
        // 数据库名'database' => 'test',
        // 数据库用户名'username' => 'root',
        // 数据库密码'password' => '',
        // 数据库连接端口'hostport' => '',
        // 数据库连接参数'params'   => [],
        // 数据库编码默认采用utf8'charset'  => 'utf8',
        // 数据库表前缀'prefix'   => 'test_',
    ],

    然后就可以直接在connect方法中传入配置参数进行切换数据库连接,例如:

    $result = Db::connect('db1')->query('select * from think_data where id = 1');
    $result = Db::connect('db2')->query('select * from think_data where id = 1');

    connect方法中的配置参数需要完整定义,并且仅仅对当此查询有效,下次调用Db类的时候还是使用默认的数据库连接。如果需要多次切换数据库查询,可以使用:

    $db1 = Db::connect('db1');
    $db2 = Db::connect('db2');
    $db1->query('select * from think_data where id = 1');
    $db2->query('select * from think_data where id = 1');

    查询构造器

    除了原生查询外,5.0还提供了数据库查询构造器,可以更方便执行数据库操作,查询构造器基于PDO实现,对不同的数据库驱动都是统一的语法。

    Db::table('think_data')
        ->insert(['id' => 18, 'name' => 'thinkphp', 'status' => 1]);
    
    由于我们在数据库配置文件中设置了数据表的前缀为think_,因此,table方法可以改成name方法,这样就不会因为数据表前缀的修改而改动CURD代码
    // 插入记录
    Db::name('data')
        ->insert(['id' => 18, 'name' => 'thinkphp']);
    
    如果使用系统提供的助手函数db则可以进一步简化查询代码如下:
    $db = db('data');
    // 插入记录$db->insert(['id' => 20, 'name' => 'thinkphp']);
    
    
    db助手函数默认会每次重新连接数据库,因此应当尽量避免多次调用

    链式操作

    使用链式操作可以完成复杂的数据库查询操作,例如:

    // 查询十个满足条件的数据 并按照id倒序排列
    $list = Db::name('data')
        ->where('status', 1)
        ->field('id,name')
        ->order('id', 'desc')
        ->limit(10)
        ->select();
    dump($list);

    查询表达式

    find方法用于查找满足条件第一个记录(即使你的查询条件有多个符合的数据),如果查询成功,返回的是一个一维数组,没有满足条件的话则默认返回null(也支持设置是否抛出异常)。
    where( 字段名,条件表达式,查询值 )

    可以支持的查询表达式包括如下:

    表达式含义
    EQ、=等于(=)
    NEQ、<>不等于(<>)
    GT、>大于(>)
    EGT、>=大于等于(>=)
    LT、<小于(<)
    ELT、<=小于等于(<=)
    LIKE模糊查询
    [NOT] BETWEEN(不在)区间查询
    [NOT] IN(不在)IN 查询
    [NOT] NULL查询字段是否(不)是NULL
    [NOT] EXISTSEXISTS查询
    EXP表达式查询,支持SQL语法

    批量方式:

    $result = Db::name('data')
        ->where([
            'id'   => [['in', [1, 2, 3]], ['between', '5,8'], 'or'],
            'name' => ['like', '%think%'],
        ])->limit(10)->select();
    dump($result);    
    select方法用于查询数据集,如果查询成功,返回的是一个二维数组,如果没有满足条件的话则返回空数组(也支持设置是否需要抛出异常)。

    获取数值

    如果仅仅是需要获取某行表的某个值,可以使用value方法;也支持获取某个列的数据,使用column方法。

    如果希望返回以id为索引的name列数据,可以改成:

    // 获取data表的name列 并且以id为索引$list = Db::name('data')
        ->where('status', 1)
        ->column('name', 'id');
    dump($list);  

    聚合查询

    支持的聚合查询方法包括:

    方法说明参数
    count统计数量统计的字段名(可选)
    max获取最大值统计的字段名(必须)
    min获取最小值统计的字段名(必须)
    avg获取平均值统计的字段名(必须)
    sum获取总分统计的字段名(必须)

    时间(日期)查询

    日期查询对create_time字段类型没有要求,可以是int/string/timestamp/datetime/date中的任何一种,系统会自动识别进行处理

    分块查询

    分块查询是为查询大量数据的需要而设计的,假如think_data表已经有超过1万条记录,但是一次性取那么大的数据会导致内存开销非常之大,但确实又有这个需要(例如查询所有的数据并导出到excel),采用分块查询可以缓解这个问题。

    系统会按照主键顺序查询,每次查询100条,如果你不希望使用主键进行查询,或者没有主键的话,则需要指定查询的排序字段(但必须是唯一的),例如:

    Db::name('user')
        ->where('status', '>', 0)
        ->chunk(100, function ($list) {
            // 处理100条记录foreach($list as $data){
    
            }
        }, 'uid');

    然后交给callback进行数据处理,处理完毕后继续查询下一个100条记录,如果你需要在中途中断后续的查询,只需要在callback方法调用中返回false即可,例如:

    Db::name('data')
        ->where('status','>',0)
        ->chunk(100,function($list){
            foreach($list as $data){
                // 返回false则中断后续查询return false;        
            }
        });
    模型的对象化操作

    默认情况下,实例化模型类后执行save操作都是执行的数据库insert操作,如果你需要实例化执行save执行数据库的update操作,请确保在save方法之前调用isUpdate方法:

    $user->isUpdate()->save();
    3.

    表单验证

    永远不要相信用户的数据,所以现在给表单提交添加数据验证。

    我们添加一个User验证器,如下:

    <?php
    namespace app\index\validate;
    
    use think\Validate;
    
    class User extends Validate{
        // 验证规则protected $rule = [
            'nickname' => 'require|min:5|token',
            'email'    => 'require|email',
            'birthday' => 'dateFormat:Y-m-d',
        ];
    }

    User验证器添加了三个属性的验证规则,分别表示:

    • 昵称必须,而且最小长度为5
    • 邮箱必须,而且必须是合法的邮件地址
    • 生日可选,如果填写的话必须为 Y-m-d格式的日期格式

    对属性可以使用多个验证规则,除非使用了require开头的规则,否则所有的验证都是可选的(也就是说有值才验证),多个验证之间用|分割,并且按照先后顺序依次进行验证,一旦某个规则验证失败,后续的规则就不会再进行验证(除非设置批量验证方式则统一返回所有的错误信息)。

    如果我们的验证规则里面使用了|,为了避免混淆则必须用数组方式定义验证规则,验证规则定义修改如下:

    <?phpnamespace app\index\validate;
    
    use think\Validate;
    
    class User extends Validate{
        // 验证规则protected $rule = [
            'nickname' => ['require', 'min'=>5, 'token'],
            'email'    => ['require', 'email'],
            'birthday' => ['dateFormat' => 'Y|m|d'],
        ];
    }

    然后对控制器的add方法则稍加修改,在save方法之前添加一个validate方法即可:

    // 新增用户数据public function add(){
        $user = new UserModel;
        if ($user->allowField(true)->validate(true)->save(input('post.'))) {
            return '用户[ ' . $user->nickname . ':' . $user->id . ' ]新增成功';
        } else {
            return $user->getError();
        }
    }

    当我们没有输入任何表单数据就直接提交的话,页面会输出结果:

    nickname不能为空

模型输出

可以输出模型实例对象为数组或者JSON

输出数组

可以使用toArray方法把当前的模型对象输出为数组。

隐藏属性

如果输出的时候需要隐藏某些属性,可以使用:

// 读取用户数据并输出数组public function read($id = ''){
    $user = UserModel::get($id);
    dump($user->hidden(['create_time','update_time'])->toArray());
}

指定属性

或者指定一些属性输出,则可以用:

// 读取用户数据并输出数组public function read($id = ''){
    $user = UserModel::get($id);
    dump($user->visible(['id','nickname','email'])->toArray());
}

追加属性

如果读取器定义了一些非数据库字段的读取,例如:

<?phpnamespace app\index\model;

use think\Model;

class User extends Model{
    // status修改器protected function getUserStatusAttr($value){
        $status = [-1 => '删除', 0 => '禁用', 1 => '正常', 2 => '待审核'];
        return $status[$value];
    }
}

而我们如果需要输出user_status属性数据的话,可以使用append方法,用法如下:

// 读取用户数据并输出数组public function read($id = ''){
    $user = UserModel::get($id);
    dump($user->append(['user_status'])->toArray());
}

再次访问 http://tp5.com/user/20 页面输出结果变成:

array (size=8)
  'id' => int 20'nickname' => string '张三' (length=6)
  'email' => string 'zhanghsan@qq.com' (length=16)
  'birthday' => string '1988/01/15' (length=10)
  'status' => int 2'create_time' => string '2016-05-02 16:40:57' (length=19)
  'update_time' => string '2016-05-02 16:40:57' (length=19)
  'user_status' => string '待审核' (length=9)

输出JSON

对于API开发而言,经常需要返回JSON格式的数据,修改read操作方法改成JSON输出:

// 读取用户数据输出JSONpublic function read($id = ''){
    $user = UserModel::get($id);
    echo $user->toJson();
}

访问 http://tp5.com/user/20 页面输出结果为:

{"id":22,"nickname":"张三","email":"zhanghsan@qq.com","birthday":"1988\/01\/15","status":2,"create_time":"2016-05-02 16:40:57","update_time":"2016-05-02 16:40:57"}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值