最近在做账单功能,需求是一键创建账单,创建时选择要复制数据的月份,即复制一份上月的数据稍作调整后作为本月或者任意月的数据。
这就需要从数据库中取出数据,修改后再插入数据库中,实际操作是发现一些问题,这里做一下总结。
一、取出数据
1、静态方法
静态方法取出的数据是对象,object,能做修改调整,但是重新插入数据库就会繁琐一些。
2、DB类
直接引用THINK的DB类,操作数据库,得到的是数组,这样不光能方便操作,也能快速的写回数据库中。
二、修改数据
1、通过THINKPHP分页后数据处理修改
如果被修改的值是静态值,可以试试分页后数据处理 (V5.0.9)
V5.0.9版本开始 支持分页类后数据直接each遍历处理,方便修改分页后的数据,而不是只能通过模型的获取器来补充字段。
1 2 3 |
$list = User::where('status',1)->paginate()->each(function($item, $key){ $item->nickname = 'think'; }); |
如果是Db类操作分页数据的话,each方法的闭包函数中需要使用返回值,例如:
1 2 3 4 |
$list = Db::name('user')->where('status',1)->paginate()->each(function($item, $key){ $item['nickname'] = 'think'; return $item; }); |
注意,一般的变量是无法传入paginate()->each方法,如果需要传入动态值,如要根据实际情况调整。
2、修改器
修改器的作用是在模型对象数据写入数据库之前进行一些必要的数据处理,修改器的标准定义如下:
1 2 3 4 5 6 |
public function setFieldNameAttr($value, $data) { // 对value值进行处理 data参数是当前全部数据 // 返回值就是实际要写入数据库的值 return $value; } |
其中FieldName对应数据表的field_name字段(注意数据表字段的规范和修改器方法定义规范,否则会导致错误)。
原则上,每个修改器应当仅处理对应字段的数据,但在必要的情况下允许同时处理多个字段。
下面是一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public function setBirthdayAttr($value, $data) { // 格式化生日数据 $birthday = strtotime($value); // 根据生日判断年龄 $age = getAgeByBirthday($birthday); // 赋值年龄数据 $this->setAttr('age', $age); return $birthday; } public function setAgeAttr($value,$data) { return floor($value); } |
之所以使用setAttr方法是确保年龄赋值操作仍然可以走单独的修改器。如果你没有额外的修改器,那么也可以写成
1 2 3 4 5 6 7 8 9 10 11 |
public function setBirthdayAttr($value, $data) { // 格式化生日数据 $birthday = strtotime($value); // 根据生日判断年龄 $age = getAgeByBirthday($birthday); // 赋值年龄数据 $this->data['age'] = $age; return $birthday; } |
注意一定不能写成
1 |
$this->age = $age; |
因为在模型内部进行数据对象的赋值,会因为和模型内部属性混淆而导致不可预知的后果。
如果你在某个修改器中可能会对其它字段进行修改,务必记得你需要额外修改的字段修改器必须已经经过赋值操作(或者已经触发过修改器)。
修改器方法不需要手动调用,按照定义规范定义好后,系统会在下面的情况下自动调用:
- 模型对象赋值;
- 调用模型的data方法,并且第二个参数传入true;
- 调用模型的save方法,并且传入数组数据;
- 显式调用模型的setAttr方法;
- 定义了该字段的自动完成。
例如User模型定义了setPasswordAttr修改器方法。
1 2 3 4 |
public function setPasswordAttr($value, $data) { return md5($value); } |
当下面这样使用的时候,保存到数据库的password字段的值就会变成md5(‘think’)后的值。
1 2 3 |
$user = User::get(1); $user->password = 'think'; $user->save(); |
如果你在一些情况下,不希望使用修改器而是想要手动控制数据,可以尝试使用下面的方法。
1 2 3 |
$user = User::get(1); $user->data('password', md5('think')); $user->save(); |
这个时候就不会经过修改器处理。
3、foreach遍历
这是我最终选择的方法。
1 2 3 4 5 6 7 8 9 10 11 |
$bill = \app\index\model\Bill::create($params,true); $bill_id = $bill->id; // $bill_info = \app\index\model\BillData::where('bill_id',$params['data_source'])->select(); 静态方法取出来是对象 $bill_data = Db::table('bill_data')->where('bill_id',$params['data_source'])->select(); foreach ($bill_data as &$v) { $v['id'] = NULL; $v['state'] = '正常'; $v['bill_id'] = $bill_id; dump($v); \app\index\model\BillData::create($v); } |
foreach方法遍历,我可以依次传入变量或者静态值,缺点是数据量大时资源消耗较大。
原创文章,作者:蓝洛水深,如若转载,请注明出处:https://blog.lanluo.cn/10316