模型2

数据集

模型的allselect查询方法返回数据集对象 think\model\Collection,该对象继承自think\Collection,因此具有数据库的数据集类的所有方法,而且还提供了额外的模型操作方法。

基本用法和数组一样,需要注意的是,如果要判断数据集是否为空,不能直接使用empty判断,而必须使用数据集对象的isEmpty方法判断

可以使用模型的hidden/visible/append/withAttr方法进行数据集的输出处理

$users = User::select();
if($users->isEmpty()){
    echo '数据集为空';
}

V5.1.23+版本开始,支持数据集的diff/intersect操作。

// 模型查询返回数据集对象
$list1 = User::where('status', 1)->field('id,name')->select();
$list2 = User::where('name', 'like', 'think')->field('id,name')->select();
// 计算差集
dump($list1->diff($list2));
// 计算交集
dump($list1->intersect($list2));

自动时间戳

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = true/false;
    // 字段类型设置
    protected $autoWriteTimestamp = 'timestamp/datetime/int';
    // 定义时间戳字段名
    protected $createTime = 'create_at';
    protected $updateTime = 'update_at';
    // 关闭自动写入update_time字段
    protected $updateTime = false;

}

一、全局开启

// 开启自动写入时间戳字段
'auto_timestamp' => true,

二、单独开启

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    protected $autoWriteTimestamp = true;
}

三、全局开启,单独关闭

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    protected $autoWriteTimestamp = false;
}

一旦配置开启的话,会自动写入create_timeupdate_time两个字段的值,默认为整型(int),如果你的时间字段不是int类型的话,可以直接使用:

// 开启自动写入时间戳字段
'auto_timestamp' => 'datetime',

或者

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    protected $autoWriteTimestamp = 'datetime';
}

默认的创建时间字段为create_time,更新时间字段为update_time,支持的字段类型包括timestamp/datetime/int

写入数据的时候,系统会自动写入create_timeupdate_time字段,而不需要定义修改器

时间字段的自动写入仅针对模型的写入方法,如果使用数据库的更新或者写入方法则无效。

时间字段输出的时候会自动进行格式转换,如果不希望自动格式化输出,可以把数据库配置文件的 datetime_format 参数值改为false

如果你的数据表字段不是默认值的话,可以按照下面的方式定义:

<?php
namespace app\index\model;

use think\Model;

class User extends Model 
{
    // 定义时间戳字段名
    protected $createTime = 'create_at';
    protected $updateTime = 'update_at';
}

如果你只需要使用create_time字段而不需要自动写入update_time,则可以单独关闭某个字段,例如:

class User extends Model 
{
    // 关闭自动写入update_time字段
    protected $updateTime = false;
}

支持动态关闭时间戳写入功能,例如你希望更新阅读数的时候不修改更新时间,可以使用isAutoWriteTimestamp方法:

$user = User::get(1);
$user->read +=1;
$user->isAutoWriteTimestamp(false)->save();

只读字段

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    protected $readonly = ['name', 'email'];
}

5.1版本支持动态设置只读字段,例如:

$user = User::get(5);
 // 更改某些字段的值
$user->name = 'TOPThink';
$user->email = 'Topthink@gmail.com';
$user->address = '上海静安区';
 // 保存更改后的用户数据
$user->readonly(['name','email'])->save();

只读字段仅针对模型的更新方法,如果使用数据库的更新方法则无效,例如下面的方式无效。

类型转换

支持给字段设置类型自动转换,会在写入和读取的时候自动进行类型转换处理,例如:

<?php
class User extends Model 
{
    protected $type = [
        'status'    =>  'integer',
        'score'     =>  'float',
        'birthday'  =>  'datetime',
        'info'      =>  'array',
    ];
}

数据库查询默认取出来的数据都是字符串类型,如果需要转换为其他的类型,需要设置

自动完成

系统支持autoinsertupdate三个属性,可以分别在写入、新增和更新的时候进行字段的自动完成机制,auto属性自动完成包含新增和更新操作

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    protected $auto = ['name', 'ip'];
    protected $insert = ['status' => 1];  
    protected $update = [];  
    
    protected function setNameAttr($value)
    {
        return strtolower($value);
    }
    
    protected function setIpAttr()
    {
        return request()->ip();
    }
}

数据自动完成如果需要写入固定的值,可以直接指定(例如上面的status字段固定写入了1),类似于数据表字段的默认值功能。

数据自动完成仍然还是调用的修改器,要注意避免数据被两次处理的可能,自动完成定义的属性不要和表单提交的冲突。

查询范围

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{

    public function scopeThinkphp($query)
    {
        $query->where('name','thinkphp')->field('id,name');
    }
    
    public function scopeAge($query)
    {
        $query->where('age','>',20)->limit(10);
    }    
    
}

使用:

// 查找name为thinkphp的用户
User::scope('thinkphp')->find();
// 查找年龄大于20的10个用户
User::scope('age')->select();
// 查找name为thinkphp的用户并且年龄大于20的10个用户
User::scope('thinkphp,age')->select();

查询范围的方法可以定义额外的参数,例如User模型类定义如下:

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
	public function scopeEmail($query, $email)
    {
    	$query->where('email', 'like', '%' . $email . '%');
    }
    
    public function scopeScore($query, $score)
    {
    	$query->where('score', '>', $score);
    }
    
}

在查询的时候可以如下使用:

// 查询email包含thinkphp和分数大于80的用户
User::email('thinkphp')->score(80)->select();

使用查询范围后,只能使用find或者select查询。

全局查询

如果你的所有查询都需要一个基础的查询范围,那么可以在模型类里面定义一个静态的base方法,例如:

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    // 定义全局的查询范围
    protected function base($query)
    {
        $query->where('status',1);
    }
}

然后,执行下面的代码:

$user = User::get(1);
//即
status = 1 AND id = 1

如果需要动态关闭/开启全局查询访问,可以使用:

// 关闭全局查询范围
User::useGlobalScope(false)->select();
// 开启全局查询范围
User::useGlobalScope(true)->select();

V5.1.26+版本开始,支持在模型里面设置globalScope属性,定义全局的查询范围

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    // 定义全局的查询范围
    protected $globalScope = ['status'];

    public function scopeStatus($query)
    {
        $query->where('status',1);
    }
}

或者使用useGlobalScope方法动态指定当前查询的全局查询范围。

User::useGlobalScope(['status'])->select();

模型输出

一、数组转换

可以使用toArray方法将当前的模型实例输出为数组,例如:

$user = User::find(1);
dump($user->toArray());

对于数据集结果一样可以直接使用(包括appendvisiblehidden方法)

注意,必须要首先调用一次Db类的方法后才能调用hidden/visible/append方法。

$user = User::find(1);
dump($user->visible(['id','name','email'])->toArray());

$user = User::find(1);
dump($user->hidden(['create_time','update_time'])->toArray());

$user = User::find(1);
dump($user->append(['status_text'])->toArray());

二、追加关联属性

支持追加一对一关联模型的属性到当前模型,例如:

$user = User::find(1);
dump($user->append(['profile' => ['email', 'nickname']])->toArray());

profile是关联定义方法名,emailnicknameProfile模型的属性。

三、JSON序列化

可以调用模型的toJson方法进行JSON序列化,toJson方法的使用和toArray一样。

$user = User::get(1);
echo $user->toJson();

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值