ThinkPHP5模型的自动处理

Published on 2016 - 12 - 20

获取器

获取器

获取器的作用是在获取数据的字段值后自动进行处理,例如,我们需要对状态值进行转换,可以使用:

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

数据表的字段会自动转换为驼峰法,一般status字段的值采用数值类型,我们可以通过获取器定义,自动转换为字符串描述。

$user = User::get(1);
echo $user->status; // 例如输出“正常”

获取器还可以定义数据表中不存在的字段,例如:

class User extends Model 
{
    public function getStatusTextAttr($value,$data)
    {
        $status = [-1=>'删除',0=>'禁用',1=>'正常',2=>'待审核'];
        return $status[$data['status']];
    }
}

获取器方法的第二个参数传入的是当前的所有数据数组。

我们就可以直接使用status_text字段的值了,例如:

$user = User::get(1);
echo $user->status_text; // 例如输出“正常”

获取器只有当获取某个数据属性的时候自动触发,如果你要获取包含修改器处理的全部数据属性的话,可以使用下面的方法:

$user = User::get(1);
// 获取全部获取器数据
dump($user->toArray());

获取原始数据

如果你定义了获取器的情况下,希望获取数据表中的原始数据,可以使用:

$user = User::get(1);
// 通过获取器获取字段
echo $user->status;
// 获取原始字段数据
echo $user->getData('status');
// 获取全部原始数据
dump($user->getData());

修改器

修改器

修改器的作用是可以在数据赋值的时候自动进行转换处理,例如:

class User extends Model 
{
    public function setNameAttr($value)
    {
        return strtolower($value);
    }
}

如下代码实际保存到数据库中的时候会转为小写

$user = new User();
$user->name = 'THINKPHP';
$user->save();
echo $user->name; // thinkphp

也可以进行序列化字段的组装:

class User extends Model 
{
    public function setNameAttr($value,$data)
    {
        return serialize($data);
    }
}

修改器方法的第二个参数会自动传入当前的所有数据数组。

批量修改

除了赋值的方式可以触发修改器外,还可以用下面的方法批量触发修改器:

$user = new User();
$data['name'] = 'THINKPHP';
$data['email'] = 'thinkphp@qq.com';
$user->data($data, true);
$user->save();
echo $user->name; // thinkphp

或者直接使用save方法触发,例如:

$user = new User();
$data['name'] = 'THINKPHP';
$data['email'] = 'thinkphp@qq.com';
$user->save($data);
echo $user->name; // thinkphp

时间戳

系统支持自动写入创建和更新的时间戳字段,有两种方式配置支持。

第一种方式,是在数据库配置文件中添加全局设置:

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

第二种是直接在单独的模型类里面设置:

protected $autoWriteTimestamp = true;

如果这两个地方设置为true,默认识别为整型int类型,如果你的时间字段不是int类型的话,例如使用datetime类型的话,可以这样设置:

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

或者

protected $autoWriteTimestamp = 'datetime';

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

写入数据的时候,系统会自动写入create_time和update_time字段,而不需要定义修改器,例如:

$user = new User();
$user->name = 'THINKPHP';
$user->save();
echo $user->create_time; // 输出类似 1462545582
echo $user->update_time; // 输出类似 1462545582

时间戳字段输出的时候一样支持获取器。

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

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

下面是修改字段后的输出代码:

$user = new User();
$user->name = 'THINKPHP';
$user->save();
echo $user->create_at; // 输出类似 1462545612
echo $user->update_at; // 输出类似 1462545612

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

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

如果不需要任何自动写入的时间戳字段的话,可以关闭时间戳自动写入功能,设置如下:

class User extends Model 
{
    // 关闭自动写入时间戳
    protected $autoWriteTimestamp = false;
}

如果是关闭全局的自动时间写入,则可以使用:

// 关闭全局自动写入时间字段
'auto_timestamp' => false,

软删除

软删除

版本 调整功能
5.0.2 deleteTime 属性改为非静态定义

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

要使用软删除功能,需要引入SoftDelete trait,例如User模型按照下面的定义就可以使用软删除功能:

namespace app\index\model;

use think\Model;
use traits\model\SoftDelete;

class User extends Model
{
    use SoftDelete;
    protected $deleteTime = 'delete_time';
}

5.0.2版本之前deleteTime属性必须使用static定义。

deleteTime属性用于定义你的软删除标记字段,ThinkPHP5的软删除功能使用时间戳类型(数据表默认值为Null),用于记录数据的删除时间。

可以用类型转换指定软删除字段的类型。

定义好模型后,我们就可以使用:

// 软删除
User::destroy(1);
// 真实删除
User::destroy(1,true);
$user = User::get(1);
// 软删除
$user->delete();
// 真实删除
$user->delete(true);

默认情况下查询的数据不包含软删除数据,如果需要包含软删除的数据,可以使用下面的方式查询:

User::withTrashed()->find();
User::withTrashed()->select();

如果仅仅需要查询软删除的数据,可以使用:

User::onlyTrashed()->find();
User::onlyTrashed()->select();

类型转换

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

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

下面是一个类型自动转换的示例:

$user = new User;
$user->status = '1';
$user->score = '90.50';
$user->birthday = '2015/5/1';
$user->info = ['a'=>1,'b'=>2];
$user->save();
var_dump($user->status); // int 1
var_dump($user->score); // float 90.5;
var_dump($user->birthday); // string '2015-05-01 00:00:00'
var_dump($user->info);// array (size=2) 'a' => int 1  'b' => int 2

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

  • integer

设置为integer(整型)后,该字段写入和输出的时候都会自动转换为整型。

  • float

该字段的值写入和输出的时候自动转换为浮点型。

  • boolean

该字段的值写入和输出的时候自动转换为布尔型。

  • array

如果设置为强制转换为array类型,系统会自动把数组编码为json格式字符串写入数据库,取出来的时候会自动解码。

  • object

该字段的值在写入的时候会自动编码为json字符串,输出的时候会自动转换为stdclass对象。

  • serialize

指定为序列化类型的话,数据会自动序列化写入,并且在读取的时候自动反序列化。

  • json

指定为json类型的话,数据会自动json_encode写入,并且在读取的时候自动json_decode处理。

  • timestamp

指定为时间戳字段类型的话,该字段的值在写入时候会自动使用strtotime生成对应的时间戳,输出的时候会自动转换为dateFormat属性定义的时间字符串格式,默认的格式为Y-m-d H:i:s,如果希望改变其他格式,可以定义如下:

class User extends Model 
{
    protected $dateFormat = 'Y/m/d';
    protected $type = [
        'status'    =>  'integer',
        'score'     =>  'float',
        'birthday'  =>  'timestamp',
    ];
}

或者在类型转换定义的时候使用:

class User extends Model 
{
    protected $type = [
        'status'    =>  'integer',
        'score'     =>  'float',
        'birthday'  =>  'timestamp:Y/m/d',
    ];
}

然后就可以

$user = User::find(1);
echo $user->birthday; // 2015/5/1
  • datetime

和timestamp类似,区别在于写入和读取数据的时候都会自动处理成时间字符串Y-m-d H:i:s的格式。

数据完成

数据自动完成指在不需要手动赋值的情况下对字段的值进行处理后写入数据库。

系统支持auto、insert和update三个属性,可以分别在写入、新增和更新的时候进行字段的自动完成机制,auto属性自动完成包含新增和更新操作,例如我们定义User模型类如下:

namespace app\index\model;

use think\Model;

class User extends Model
{
    protected $auto = ['name', 'ip', 'password'];
    protected $insert = ['status' => 1];  
    protected $update = [];  

    protected function setNameAttr($value)
    {
        return strtolower($value);
    }

    protected function setIpAttr()
    {
        return request()->ip();
    }

    protected function setPasswordAttr($value)
    {
        return md5($value);
    }
}

在新增数据的时候,会对name、ip和 status 字段自动完成或者处理。

$user = new User;
$user->name = 'ThinkPHP';
$user->save();
echo $user->name; // thinkphp
echo $user->status; // 1

在保存操作的时候,会自动处理name字段的值及完成ip字段的赋值。

$user = User::find(1);
$user->name = 'THINKPHP';
$user->save();
echo $user->name; // thinkphp
echo $user->ip; // 127.0.0.1

参考文档