Completed
Push — 6.0 ( b1ea4f...d19a1f )
by liu
03:36
created

Attribute   F

Complexity

Total Complexity 116

Size/Duplication

Total Lines 626
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 232
dl 0
loc 626
ccs 0
cts 226
cp 0
rs 2
c 0
b 0
f 0
wmc 116

21 Methods

Rating   Name   Duplication   Size   Complexity  
A setAttrs() 0 5 2
A getOrigin() 0 7 3
A set() 0 5 1
A getData() 0 15 4
A getPk() 0 3 1
A allowField() 0 5 1
B getChangedData() 0 18 9
A getKey() 0 9 3
A appendData() 0 9 2
B data() 0 30 7
A getRealFieldName() 0 3 2
A isPk() 0 11 5
A readOnly() 0 5 1
A getAttr() 0 11 2
B setAttr() 0 31 9
D writeTransform() 0 61 22
B getValue() 0 35 11
A getRelationValue() 0 5 2
A getJsonValue() 0 11 3
A withAttribute() 0 19 4
D readTransform() 0 62 22

How to fix   Complexity   

Complex Class

Complex classes like Attribute often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Attribute, and based on these observations, apply Extract Interface, too.

1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think\model\concern;
14
15
use InvalidArgumentException;
16
use think\App;
17
use think\db\Raw;
18
use think\model\Relation;
19
20
/**
21
 * 模型数据处理
22
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
23
trait Attribute
24
{
25
    /**
26
     * 数据表主键 复合主键使用数组定义
27
     * @var string|array
28
     */
29
    protected $pk = 'id';
30
31
    /**
32
     * 数据表字段信息 留空则自动获取
33
     * @var array
34
     */
35
    protected $schema = [];
36
37
    /**
38
     * 当前允许写入的字段
39
     * @var array
40
     */
41
    protected $field = [];
42
43
    /**
44
     * 字段自动类型转换
45
     * @var array
46
     */
47
    protected $type = [];
48
49
    /**
50
     * 数据表废弃字段
51
     * @var array
52
     */
53
    protected $disuse = [];
54
55
    /**
56
     * 数据表只读字段
57
     * @var array
58
     */
59
    protected $readonly = [];
60
61
    /**
62
     * 当前模型数据
63
     * @var array
64
     */
65
    private $data = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "data" must be prefixed with an underscore
Loading history...
66
67
    /**
68
     * 原始数据
69
     * @var array
70
     */
71
    private $origin = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "origin" must be prefixed with an underscore
Loading history...
72
73
    /**
74
     * JSON数据表字段
75
     * @var array
76
     */
77
    protected $json = [];
78
79
    /**
80
     * JSON数据表字段类型
81
     * @var array
82
     */
83
    protected $jsonType = [];
84
85
    /**
86
     * JSON数据取出是否需要转换为数组
87
     * @var bool
88
     */
89
    protected $jsonAssoc = false;
90
91
    /**
92
     * 是否严格字段大小写
93
     * @var bool
94
     */
95
    protected $strict = true;
96
97
    /**
98
     * 修改器执行记录
99
     * @var array
100
     */
101
    private $set = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "set" must be prefixed with an underscore
Loading history...
102
103
    /**
104
     * 动态获取器
105
     * @var array
106
     */
107
    private $withAttr = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "withAttr" must be prefixed with an underscore
Loading history...
108
109
    /**
110
     * 获取模型对象的主键
111
     * @access public
112
     * @return string|array
113
     */
114
    public function getPk()
115
    {
116
        return $this->pk;
117
    }
118
119
    /**
120
     * 判断一个字段名是否为主键字段
121
     * @access public
122
     * @param  string $key 名称
123
     * @return bool
124
     */
125
    protected function isPk(string $key): bool
126
    {
127
        $pk = $this->getPk();
128
129
        if (is_string($pk) && $pk == $key) {
130
            return true;
131
        } elseif (is_array($pk) && in_array($key, $pk)) {
132
            return true;
133
        }
134
135
        return false;
136
    }
137
138
    /**
139
     * 获取模型对象的主键值
140
     * @access public
141
     * @return mixed
142
     */
143
    public function getKey()
144
    {
145
        $pk = $this->getPk();
146
147
        if (is_string($pk) && array_key_exists($pk, $this->data)) {
148
            return $this->data[$pk];
149
        }
150
151
        return;
152
    }
153
154
    /**
155
     * 设置允许写入的字段
156
     * @access public
157
     * @param  array $field 允许写入的字段
158
     * @return $this
159
     */
160
    public function allowField(array $field)
161
    {
162
        $this->field = $field;
163
164
        return $this;
165
    }
166
167
    /**
168
     * 设置只读字段
169
     * @access public
170
     * @param  array $field 只读字段
171
     * @return $this
172
     */
173
    public function readOnly(array $field)
174
    {
175
        $this->readonly = $field;
176
177
        return $this;
178
    }
179
180
    /**
181
     * 获取实际的字段名
182
     * @access public
183
     * @param  string $name 字段名
184
     * @return string
185
     */
186
    protected function getRealFieldName(string $name): string
187
    {
188
        return $this->strict ? $name : App::parseName($name);
189
    }
190
191
    /**
192
     * 设置数据对象值
193
     * @access public
194
     * @param  array    $data  数据
195
     * @param  bool     $set   是否调用修改器
196
     * @param  array    $allow 允许的字段名
197
     * @return $this
198
     */
199
    public function data(array $data, bool $set = false, array $allow = [])
200
    {
201
        // 清空数据
202
        $this->data = [];
203
204
        // 废弃字段
205
        foreach ($this->disuse as $key) {
206
            if (array_key_exists($key, $data)) {
207
                unset($data[$key]);
208
            }
209
        }
210
211
        if (!empty($allow)) {
212
            $result = [];
213
            foreach ($allow as $name) {
214
                if (isset($data[$name])) {
215
                    $result[$name] = $data[$name];
216
                }
217
            }
218
            $data = $result;
219
        }
220
221
        if ($set) {
222
            // 数据对象赋值
223
            $this->setAttrs($data);
224
        } else {
225
            $this->data = $data;
226
        }
227
228
        return $this;
229
    }
230
231
    /**
232
     * 批量追加数据对象值
233
     * @access public
234
     * @param  array $data  数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
235
     * @param  bool  $set   是否需要进行数据处理
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
236
     * @return $this
237
     */
238
    public function appendData(array $data, bool $set = false)
239
    {
240
        if ($set) {
241
            $this->setAttrs($data);
242
        } else {
243
            $this->data = array_merge($this->data, $data);
244
        }
245
246
        return $this;
247
    }
248
249
    /**
250
     * 获取对象原始数据 如果不存在指定字段返回null
251
     * @access public
252
     * @param  string $name 字段名 留空获取全部
253
     * @return mixed
254
     */
255
    public function getOrigin(string $name = null)
256
    {
257
        if (is_null($name)) {
258
            return $this->origin;
259
        }
260
261
        return array_key_exists($name, $this->origin) ? $this->origin[$name] : null;
262
    }
263
264
    /**
265
     * 获取对象原始数据 如果不存在指定字段返回false
266
     * @access public
267
     * @param  string $name 字段名 留空获取全部
268
     * @return mixed
269
     * @throws InvalidArgumentException
270
     */
271
    public function getData(string $name = null)
272
    {
273
        if (is_null($name)) {
274
            return $this->data;
275
        }
276
277
        $fieldName = $this->getRealFieldName($name);
278
279
        if (array_key_exists($fieldName, $this->data)) {
280
            return $this->data[$fieldName];
281
        } elseif (array_key_exists($name, $this->relation)) {
282
            return $this->relation[$name];
283
        }
284
285
        throw new InvalidArgumentException('property not exists:' . static::class . '->' . $name);
286
    }
287
288
    /**
289
     * 获取变化的数据 并排除只读数据
290
     * @access public
291
     * @return array
292
     */
293
    public function getChangedData(): array
294
    {
295
        $data = $this->force ? $this->data : array_udiff_assoc($this->data, $this->origin, function ($a, $b) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
296
            if ((empty($a) || empty($b)) && $a !== $b) {
297
                return 1;
298
            }
299
300
            return is_object($a) || $a != $b ? 1 : 0;
301
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
302
303
        // 只读字段不允许更新
304
        foreach ($this->readonly as $key => $field) {
305
            if (isset($data[$field])) {
306
                unset($data[$field]);
307
            }
308
        }
309
310
        return $data;
311
    }
312
313
    /**
314
     * 直接设置数据对象值
315
     * @access public
316
     * @param  string $name  属性名
317
     * @param  mixed  $value 值
318
     * @return void
319
     */
320
    public function set(string $name, $value): void
321
    {
322
        $name = $this->getRealFieldName($name);
323
324
        $this->data[$name] = $value;
325
    }
326
327
    /**
328
     * 通过修改器 批量设置数据对象值
329
     * @access public
330
     * @param  array $data  数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
331
     * @return void
332
     */
333
    public function setAttrs(array $data): void
334
    {
335
        // 进行数据处理
336
        foreach ($data as $key => $value) {
337
            $this->setAttr($key, $value, $data);
338
        }
339
    }
340
341
    /**
342
     * 通过修改器 设置数据对象值
343
     * @access public
344
     * @param  string $name  属性名
345
     * @param  mixed  $value 属性值
346
     * @param  array  $data  数据
347
     * @return void
348
     */
349
    public function setAttr(string $name, $value, array $data = []): void
350
    {
351
        $name = $this->getRealFieldName($name);
352
353
        if (isset($this->set[$name])) {
354
            return;
355
        }
356
357
        if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime])) {
358
            // 自动写入的时间戳字段
359
            $value = $this->autoWriteTimestamp($name);
0 ignored issues
show
Bug introduced by
It seems like autoWriteTimestamp() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

359
            /** @scrutinizer ignore-call */ 
360
            $value = $this->autoWriteTimestamp($name);
Loading history...
360
        } else {
361
            // 检测修改器
362
            $method = 'set' . App::parseName($name, 1) . 'Attr';
363
364
            if (method_exists($this, $method)) {
365
                $array = $this->data;
366
                $value = $this->$method($value, array_merge($this->data, $data));
367
368
                $this->set[$name] = true;
369
                if (is_null($value) && $array !== $this->data) {
370
                    return;
371
                }
372
            } elseif (isset($this->type[$name])) {
373
                // 类型转换
374
                $value = $this->writeTransform($value, $this->type[$name]);
375
            }
376
        }
377
378
        // 设置数据对象属性
379
        $this->data[$name] = $value;
380
    }
381
382
    /**
383
     * 数据写入 类型转换
384
     * @access protected
385
     * @param  mixed        $value 值
386
     * @param  string|array $type  要转换的类型
387
     * @return mixed
388
     */
389
    protected function writeTransform($value, $type)
390
    {
391
        if (is_null($value)) {
392
            return;
393
        }
394
395
        if ($value instanceof Raw) {
396
            return $value;
397
        }
398
399
        if (is_array($type)) {
400
            list($type, $param) = $type;
401
        } elseif (strpos($type, ':')) {
402
            list($type, $param) = explode(':', $type, 2);
403
        }
404
405
        switch ($type) {
406
            case 'integer':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
407
                $value = (int) $value;
408
                break;
409
            case 'float':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
410
                if (empty($param)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
411
                    $value = (float) $value;
412
                } else {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
413
                    $value = (float) number_format($value, $param, '.', '');
414
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
415
                break;
416
            case 'boolean':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
417
                $value = (bool) $value;
418
                break;
419
            case 'timestamp':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
420
                if (!is_numeric($value)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
421
                    $value = strtotime($value);
422
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
423
                break;
424
            case 'datetime':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
425
                $value = is_numeric($value) ? $value : strtotime($value);
426
                $value = $this->formatDateTime('Y-m-d H:i:s.u', $value);
0 ignored issues
show
Bug introduced by
It seems like formatDateTime() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

426
                /** @scrutinizer ignore-call */ 
427
                $value = $this->formatDateTime('Y-m-d H:i:s.u', $value);
Loading history...
427
                break;
428
            case 'object':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
429
                if (is_object($value)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
430
                    $value = json_encode($value, JSON_FORCE_OBJECT);
431
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
432
                break;
433
            case 'array':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
434
                $value = (array) $value;
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
435
            case 'json':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
436
                $option = !empty($param) ? (int) $param : JSON_UNESCAPED_UNICODE;
437
                $value  = json_encode($value, $option);
438
                break;
439
            case 'serialize':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
440
                $value = serialize($value);
441
                break;
442
            default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
443
                if (is_object($value) && false !== strpos($type, '\\') && method_exists($value, '__toString')) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
444
                    // 对象类型
445
                    $value = $value->__toString();
446
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
447
        }
448
449
        return $value;
450
    }
451
452
    /**
453
     * 获取器 获取数据对象的值
454
     * @access public
455
     * @param  string $name 名称
456
     * @return mixed
457
     * @throws InvalidArgumentException
458
     */
459
    public function getAttr(string $name)
460
    {
461
        try {
462
            $relation = false;
463
            $value    = $this->getData($name);
464
        } catch (InvalidArgumentException $e) {
465
            $relation = $this->isRelationAttr($name);
0 ignored issues
show
Bug introduced by
It seems like isRelationAttr() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

465
            /** @scrutinizer ignore-call */ 
466
            $relation = $this->isRelationAttr($name);
Loading history...
466
            $value    = null;
467
        }
468
469
        return $this->getValue($name, $value, $relation);
470
    }
471
472
    /**
473
     * 获取经过获取器处理后的数据对象的值
474
     * @access protected
475
     * @param  string      $name 字段名称
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 1 found
Loading history...
476
     * @param  mixed       $value 字段值
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
477
     * @param  bool|string $relation 是否为关联属性或者关联名
478
     * @return mixed
479
     * @throws InvalidArgumentException
480
     */
481
    protected function getValue(string $name, $value, $relation = false)
482
    {
483
        // 检测属性获取器
484
        $fieldName = $this->getRealFieldName($name);
485
        $method    = 'get' . App::parseName($name, 1) . 'Attr';
486
487
        if (isset($this->withAttr[$fieldName])) {
488
            if ($relation) {
489
                $value = $this->getRelationValue($name, $relation);
0 ignored issues
show
Bug introduced by
It seems like $relation can also be of type true; however, parameter $relation of think\model\concern\Attribute::getRelationValue() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

489
                $value = $this->getRelationValue($name, /** @scrutinizer ignore-type */ $relation);
Loading history...
490
            }
491
492
            if (in_array($fieldName, $this->json) && is_array($this->withAttr[$fieldName])) {
493
                $value = $this->getJsonValue($fieldName, $value);
494
            } else {
495
                $closure = $this->withAttr[$fieldName];
496
                $value   = $closure($value, $this->data);
497
            }
498
        } elseif (method_exists($this, $method)) {
499
            if ($relation) {
500
                $value = $this->getRelationValue($name, $relation);
501
            }
502
503
            $value = $this->$method($value, $this->data);
504
        } elseif (isset($this->type[$fieldName])) {
505
            // 类型转换
506
            $value = $this->readTransform($value, $this->type[$fieldName]);
507
        } elseif ($this->autoWriteTimestamp && in_array($fieldName, [$this->createTime, $this->updateTime])) {
508
            $value = $this->getTimestampValue($value);
0 ignored issues
show
Bug introduced by
It seems like getTimestampValue() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

508
            /** @scrutinizer ignore-call */ 
509
            $value = $this->getTimestampValue($value);
Loading history...
509
        } elseif ($relation) {
510
            $value = $this->getRelationValue($name, $relation);
511
            // 保存关联对象值
512
            $this->relation[$name] = $value;
0 ignored issues
show
Bug Best Practice introduced by
The property relation does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
513
        }
514
515
        return $value;
516
    }
517
518
    /**
519
     * 获取JSON字段属性值
520
     * @access protected
521
     * @param  string $name  属性名
522
     * @param  mixed  $value JSON数据
523
     * @return mixed
524
     */
525
    protected function getJsonValue($name, $value)
526
    {
527
        foreach ($this->withAttr[$name] as $key => $closure) {
528
            if ($this->jsonAssoc) {
529
                $value[$key] = $closure($value[$key], $value);
530
            } else {
531
                $value->$key = $closure($value->$key, $value);
532
            }
533
        }
534
535
        return $value;
536
    }
537
538
    /**
539
     * 获取关联属性值
540
     * @access protected
541
     * @param  string $name     属性名
542
     * @param  string $relation 关联名
543
     * @return mixed
544
     */
545
    protected function getRelationValue(string $name, string $relation)
546
    {
547
        $modelRelation = $this->$relation();
548
549
        return $modelRelation instanceof Relation ? $this->getRelationData($modelRelation) : null;
0 ignored issues
show
Bug introduced by
The method getRelationData() does not exist on think\model\concern\Attribute. Did you maybe mean getRelationValue()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

549
        return $modelRelation instanceof Relation ? $this->/** @scrutinizer ignore-call */ getRelationData($modelRelation) : null;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
550
    }
551
552
    /**
553
     * 数据读取 类型转换
554
     * @access protected
555
     * @param  mixed        $value 值
556
     * @param  string|array $type  要转换的类型
557
     * @return mixed
558
     */
559
    protected function readTransform($value, $type)
560
    {
561
        if (is_null($value)) {
562
            return;
563
        }
564
565
        if (is_array($type)) {
566
            list($type, $param) = $type;
567
        } elseif (strpos($type, ':')) {
568
            list($type, $param) = explode(':', $type, 2);
569
        }
570
571
        switch ($type) {
572
            case 'integer':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
573
                $value = (int) $value;
574
                break;
575
            case 'float':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
576
                if (empty($param)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
577
                    $value = (float) $value;
578
                } else {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
579
                    $value = (float) number_format($value, $param, '.', '');
580
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
581
                break;
582
            case 'boolean':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
583
                $value = (bool) $value;
584
                break;
585
            case 'timestamp':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
586
                if (!is_null($value)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
587
                    $format = !empty($param) ? $param : $this->dateFormat;
588
                    $value  = $this->formatDateTime($format, $value, true);
589
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
590
                break;
591
            case 'datetime':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
592
                if (!is_null($value)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
593
                    $format = !empty($param) ? $param : $this->dateFormat;
594
                    $value  = $this->formatDateTime($format, $value);
595
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
596
                break;
597
            case 'json':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
598
                $value = json_decode($value, true);
599
                break;
600
            case 'array':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
601
                $value = empty($value) ? [] : json_decode($value, true);
602
                break;
603
            case 'object':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
604
                $value = empty($value) ? new \stdClass() : json_decode($value);
605
                break;
606
            case 'serialize':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
607
                try {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
608
                    $value = unserialize($value);
609
                } catch (\Exception $e) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
610
                    $value = null;
611
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
612
                break;
613
            default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
614
                if (false !== strpos($type, '\\')) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
615
                    // 对象类型
616
                    $value = new $type($value);
617
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
618
        }
619
620
        return $value;
621
    }
622
623
    /**
624
     * 设置数据字段获取器
625
     * @access public
626
     * @param  string|array $name       字段名
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 7 found
Loading history...
627
     * @param  callable     $callback   闭包获取器
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
628
     * @return $this
629
     */
630
    public function withAttribute($name, callable $callback = null)
631
    {
632
        if (is_array($name)) {
633
            foreach ($name as $key => $val) {
634
                $this->withAttribute($key, $val);
635
            }
636
        } else {
637
            $name = $this->getRealFieldName($name);
638
639
            if (strpos($name, '.')) {
640
                list($name, $key) = explode('.', $name);
641
642
                $this->withAttr[$name][$key] = $callback;
643
            } else {
644
                $this->withAttr[$name] = $callback;
645
            }
646
        }
647
648
        return $this;
649
    }
650
651
}
652