模型查询和数据库查询方法的区别在于 模型中的查询的数据在获取时经过获取器处理 及对象化的获取方式

模型查询除了使用自身的查询方法 可用数据库的查询构造器 返回模型对象实例
但如果直接调用查询对象的方法 IDE可能无法完成自动提示

获取单个数据

// 取出主键为1的数据
$user = User::get(1);
echo $user->name;// 查询构造器查询满足条件的数据
$user = User::where('name', 'think')->find();
echo $user->name;

模型用get还是find方法查询 返回当前模型的对象实例
除了获取模型数据外 还可以使用模型的方法

V5.1.5+ 模型getOrFail用于查询 当查询的数据不存在的时候抛出ModelNotFound异常

模型内部获取模型数据 不要使用$this->name的方式来获取数据
请使用$this->getAttr('name')

获取多个数据

// 根据主键获取多个数据
$list = User::all('1,2,3');// 或使用数组
$list = User::all([1,2,3]);// 数据集遍历操作
foreach($list as $key=>$user){
echo $user->name;
}

查询构造器:

// 使用查询构造器查询
$list = User::where('status', 1)->limit(3)->order('id', 'asc')->select();
foreach($list as $key=>$user){
echo $user->name;
}

查询构造器方式的查询支持更多的连贯操作 包括排序、数量限制等

自定义数据集对象

模型allselect方法返回包含多个模型实例的数据集对象(默认为think\model\Collection
支持在模型中单独设置查询数据集的返回对象的名称

use thinkModel;
class User extends Model{// 设置返回数据集的对象名
protected $resultSetType = 'app\common\Collection';
}

resultSetType属性用于设置自定义的数据集使用的类名 该类应当继承系统的think\model\Collection

查询构造器

模型中可调用数据库的链式操作和查询方法 充分利用数据库的查询构造器的优势

User::where('id',10)->find();
User::where('status',1)->order('id desc')->select();
User::where('status',1)->limit(10)->select();

查询构造器直接使用静态方法调用 无需实例化模型

获取某个字段或某个列的值

// 获取某个用户的积分
User::where('id',10)->value('score');// 获取某个列的所有值
User::where('status',1)->column('name');// 以id为索引
User::where('status',1)->column('name','id');

valuecolumn方法返回的不再是个模型对象实例
纯粹的值或某个列的数组

动态查询

数据库的动态查询方法

// 根据name字段查询用户
$user = User::getByName('think');
// 根据email字段查询用户
$user = User::getByEmail('think@qq.com');

聚合查询

模型中调用数据库的聚合方法查询

User::count();
User::where('status','>',0)->count();
User::where('status',1)->avg('score');
User::max('score');

数据分批处理

模型对返回的数据分批处理
在处理大数据时非常有用

User::chunk(100,function($users) {
foreach($users as $user){// 处理user模型对象}
});

使用游标查询

模型用数据库的cursor方法游标查询 返回生成器对象

foreach(User::where('status', 1)->cursor() as $user){
echo $user->name;
}

user变量是个模型对象实例

查询缓存

getall方法查询缓存 直接在第二个参数传入true表示开启查询缓存

$user = User::get(1,true);$list  = User::all('1,2,3',true);

要设置缓存标识 则必须在第三个参数传入缓存标识

$user = User::get(1,'','user');$list  = User::all('1,2,3','','user_list');

主库读取

分布式数据库 写入数据后立刻进行该数据的读取 会导致数据读取失败 原因是数据库同步尚未完成

规范的解决方案是在写入数据后 不马上从从库读取 而应该调用master方法读取主库

$user   = new User;
$user->name = 'think';
$user->email = 'think@qq.com';
$user->save();// 从主库读取数据
$user->master()->get($user->id);

或对关键的逻辑启用事务 在事务中的数据库操作都是基于主库的

V5.1.12+开始 在数据库配置文件中设置

// 主库写入后从主从库读取
'read_master'=> true

设置开启后 模型有写入操作 那么该请求后续的同个模型的读操作都会自动从主库读取。

如果只需要对某个模型生效 在完成主库写入操作后 执行下模型类的readMaster方法

$user      = new User;
$user->name     = 'think';
$user->email    = 'think@qq.com';
$user->save();// 从主库读取数据
$user->readMaster(true)->get($user->id);

上述设置和方法仅对模型查询有效
直接调用Db类查询无效

最佳实践

最佳实践原则
模型外部使用静态方法进行查询
内部使用动态方法查询 包括使用数据库的查询构造器。
模型的查询始终返回对象实例 但可以和数组一样使用