Thinkphp快速入门(五)

文章目录

      • 数据库字段缓存
      • 模型查询
        • where条件
        • 执行查询
        • 限制要查询的字段
      • 模型关联
        • 一对一关联
          • 关系定义
          • 关联数据获取
          • hasWhere 以关联限制查询
        • 一对多关联
          • 关联定义
          • 关联数据获取
          • hasWher | has 以关联限制查询

数据库字段缓存

由于tp进行数据查询,新增,修改,删除等都会进行(SHOW FULL COLUMNS FROM

)获取数据表字段及其数据类型对应关系
每次都进行查询有点浪费资源
提供两种解决方式

# 第一种
# tp config/database.php 中提供了开启数据库字段缓存
# 将 fields_cache 设置成true
fields_cache => true
# 查询过一次后,会生成缓存文件,只要缓存在就去查缓存
# 如果数据字段变更后,可以通过 php think optimize:schema 应用名 (多应用)
# php think optimize:schema (单应用)
# 更新字段缓存
php think optimize:schema admin
    # 第二种
    # 通过设置模型的schema属性
    # 来告知数据库字段与类型对应关系

    protected $schema = [
        'username' => 'string',
        'password' => 'string',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

模型查询

where条件
        $user = new User();
        # where($field,$op,$condition)
        # $field 字段
        # $op 比较符 >,<,=....
        # $condition 比较条件

        #当使用等于条件$op可以省略
        $user->where('id', 1);
        # 等价与
        $user->where('id', '=', 1);

        #like语句
        $user->where('username', 'like', '%username%');

        # 多个条件可以通过链式操作
        # 也可以给where 方法 传递数组代表多个where条件
        # SELECT * FROM `user` WHERE ( `id` = '1' AND `username` LIKE '%username%' )
        # 可以写成
        $user->where([['id', '=', 1], ['username', 'like', '%username%']]);

        # or 条件
        # SELECT * FROM `user` WHERE ( `id` = '1' OR `username` LIKE '%username%' )
        $user->where('id', 1)->whereOr('username', 'like', '%username%');

        # where中传闭包可以将条件放到一个括号内(当成一个整体的where条件)
        # SELECT * FROM `user` WHERE ( ( `id` = '1' AND `status` = '1' ) OR `username` LIKE '%username%' )
        # 查找 id=1,status = 1 或者 username 中包含username的数据
        $user->where(function ($query) {
            $query->where('id', 1)->where('status', 1);
        })->whereOr('username', 'like', '%username%');
        # 如果不使用闭包
        $user->where('id', 1)->where('status', 1)->whereOr('username', 'like', '%username%')
        # 执行的是 SELECT * FROM `user` WHERE ( `id` = '1' AND `status` = '1' OR `username` LIKE '%username%' )
        # 查找id=1,status =1 或者 id = 1,username 中包含username的数据
执行查询
        $user = new User();
        # find 查找一条
        $user->where('id', '>', 1)->find();
        # select() 查找多条
        $user->where('id', '>', 1)->select();
限制要查询的字段
        $user = new User();
        # 通过field 限制要查询的字段
        # 只查找id,username 字段
        $user->where('id', '>', 1)->field(['id', 'username'])->find();

模型关联

一对一关联
关系定义

user(用户表),post(文章表)
假设用户和文章表一对一
在User模型中使用hasOne声明一个方法

# user模型中 声明post方法指明user和post表一对一关系
# 关联关系 user.id = post.user_id
public function post()
{
  # 两者都属于一对一关系
  # 只是强调概念不一样
  # 强调user含有文章
  return $this->hasOne(Post::class, 'user_id', 'id');
  # 强调user属于某个文章
  return $this->belongsTo(Post::class, 'id', 'user_id');
}
关联数据获取
# 第一种方法获取关联数据
$user = new User();
$userInstance = $user->where('id', '>', 0)->find();
# 调用声明的关联函数来获取关联数据
$userInstance->post();

# 第2种方法通过with获取关联数据
$user = new User();
$userInstance = $user->where('id', '>', 0)->with('post')->select();
# 可以限制关联要查的字段,记得一定要查关联的字段
# 可以限制关联查询的条件
$userInstance = $user->where('id', '>', 0)->with(['post' => function ($query) {
# 限制查询post.id > 1的文章数据
# user_id 一定要查,否则 $userInstance[0]->post 是null(不查user_id则无法把post数据添加到user模型上去)
$query->where('id', '>', 1)->field(['title', 'user_id']);
}])->select();
#输出第一个用户的文章的标题
$userInstance[0]->post->title;
hasWhere 以关联限制查询

模型的一对一关联使用的不是join查询
数据是分开查询的
以user和post为例
先查user满足条件的数据,取出关联字段得到user_id 数组 user_ids
再查post.user_id in (user_ids) 中的数据
那么怎么查有文章的用户呢

        $user = new User();
        # 通过hasWhere过滤查找有文章的用户且用户id > 1
        # id > 1 是user上的条件,需要带上表名 不能直接写id(post中也有id,分不清是谁的id)
        $user->where('user.id', '>', 1)->hasWhere('post')->select();

我想查找一篇文章是那个用户写的呢

        $user = new User();
        # hasWhere第二个参数可以限制查询条件
        # 查找用户,用户id > 1,用户需要有文章且文章的title叫做将进酒
        $user->where('user.id', '>', 1)->hasWhere('post', function ($query) {
            $query->where('title', '将进酒');
        })->find();

hasWhere局限性
体现在不能像laravel的model模型一样进行嵌套过滤
假设user和post文章表一对一(user.id = post.user_id)
post属于某一个文章类型post_type(post.type_id = post_type.id)
如果我要查一个用户,该用户需要满足有文章且文章类型属于诗歌
用tp的模型的hasWhere无法得到该结果

        $user = new User();
        # hasWhere不支持嵌套
        # 如果像laravel的话,应该可以这么写
        # 可惜不行
        $user->where('id', '>', 1)->hasWhere('post', function ($query) {
            $query->hasWhere('type', function ($query) {
                $query->where('name', '诗歌');
            });
        })->find();

通过关联新增,修改,删除

        # 新增 user, post
        $user = User::create(['username' => 'test_01', 'password' => '123456']);
        # post 是user中定义的关联方法
        $user->post()->save(['title' => '将进酒', 'type_id' => 1]);
        # 等价于
        # Post::create(['user_id'=>$user->id,'title' => '将进酒', 'type_id' => 1]);
        
        # 通过关联修改post
        $user = User::find(7);
        # 新增是post()->save(),修改是post->save()
        $user->post->save(['title' => '新将进酒']);
        
        # 通过关联删除post
        $user = User::find(7);
        $user->post->delete();
一对多关联
关联定义

User model 中定义

    public function post()
    {
        # 两种声明方式
        # 1.使用hasMany声明一个用户有多个文章
        return $this->hasMany(Post::class, 'user_id', 'id');
        # 2.使用belongsToMany声明一个用户属于多个文章
        return $this->belongsToMany(Post::class, 'id', 'user_id');
    }
关联数据获取
        # 用法和一对一的一样
        # 通过with查询关联数据
        $user = User::where('id', '=', 7)->with('post')->find();
        $posts = $user->post;
        
        # 通过声明的关联函数获取关联数据
        $user = User::where('id', 7)->find();
        $posts = $user->post();
        
        # 由于使用的是一对多关联
        # $user->post | $user->post() 返回的是多条 所以使用foreach遍历
        # 一对一关联直接 $user->post->title | $user->post()->title 即可
        foreach ($posts as $post) {
            echo $post->title;
        }
hasWher | has 以关联限制查询

查询有文章的用户

        $model = new User();
        $user = $model->hasWhere('post')->select();

查询文章数大于等于两篇的用户

        $model = new User();
        $user = $model->has('post', '>=', 2)->select();

查找文章大于两篇的(要求文章type_id = 1,type_id = 1 意思是诗歌类型)
查找用户,要求用户发表过两篇及以上的诗歌文章

        # 这时候使用model模型就有点无力了
        # tp 的model 没有laravel的强大
        # 改用DB类实现
        # SELECT `user`.* FROM `user` LEFT JOIN `post` ON `user`.`id`=`post`.`user_id` WHERE `post`.`type_id` = '1' GROUP BY `user`.`id` HAVING count(post.id) >= 2
        $user = Db::name('user')
            ->leftJoin('post', 'user.id  = post.user_id')
            ->field(['user.*'])
            ->where('post.type_id', 1)
            ->group('user.id')
            ->having("count(post.id) >= 2")
            ->select();

你可能感兴趣的:(PHP,#,Thinkphp,php,thinkphp)