Completed
Push — 6.0 ( be4b12...d71786 )
by liu
06:57
created

Model::__wakeup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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;
14
15
use ArrayAccess;
16
use Closure;
17
use JsonSerializable;
18
use think\db\Query;
19
20
/**
21
 * Class Model
22
 * @package think
0 ignored issues
show
Coding Style introduced by
Package name "think" is not valid; consider "Think" instead
Loading history...
23
 * @mixin Query
1 ignored issue
show
Coding Style introduced by
Tag value for @mixin tag indented incorrectly; expected 3 spaces but found 1
Loading history...
24
 * @method Query where(mixed $field, string $op = null, mixed $condition = null) static 查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
25
 * @method Query whereTime(string $field, string $op, mixed $range = null) static 查询日期和时间
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
26
 * @method Query whereBetweenTime(string $field, mixed $startTime, mixed $endTime) static 查询日期或者时间范围
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
27
 * @method Query whereBetweenTimeField(string $startField, string $endField) static 查询当前时间在两个时间字段范围
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
28
 * @method Query whereYear(string $field, string $year = 'this year') static 查询某年
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
29
 * @method Query whereMonth(string $field, string $month = 'this month') static 查询某月
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
30
 * @method Query whereDay(string $field, string $day = 'today') static 查询某日
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
31
 * @method Query whereRaw(string $where, array $bind = []) static 表达式查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
32
 * @method Query whereExp(string $field, string $condition, array $bind = []) static 字段表达式查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
33
 * @method Query when(mixed $condition, mixed $query, mixed $otherwise = null) static 条件查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
34
 * @method Query join(mixed $join, mixed $condition = null, string $type = 'INNER') static JOIN查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
35
 * @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
36
 * @method Query with(mixed $with) static 关联预载入
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
37
 * @method Query count(string $field) static Count统计查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
38
 * @method Query min(string $field) static Min统计查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
39
 * @method Query max(string $field) static Max统计查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
40
 * @method Query sum(string $field) static SUM统计查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
41
 * @method Query avg(string $field) static Avg统计查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
42
 * @method Query field(mixed $field, boolean $except = false) static 指定查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
43
 * @method Query fieldRaw(string $field, array $bind = []) static 指定查询字段
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
44
 * @method Query union(mixed $union, boolean $all = false) static UNION查询
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
45
 * @method Query limit(mixed $offset, integer $length = null) static 查询LIMIT
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
46
 * @method Query order(mixed $field, string $order = null) static 查询ORDER
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
47
 * @method Query orderRaw(string $field, array $bind = []) static 查询ORDER
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
48
 * @method Query cache(mixed $key = null, integer $expire = null) static 设置查询缓存
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
49
 * @method mixed value(string $field) static 获取某个字段的值
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
50
 * @method array column(string $field, string $key = '') static 获取某个列的值
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
51
 * @method Model find(mixed $data = null) static 查询单个记录 不存在返回Null
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
52
 * @method Model findOrEmpty(mixed $data = null) static 查询单个记录 不存在返回空模型
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
53
 * @method \think\model\Collection select(mixed $data = null) static 查询多个记录
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
54
 * @method Model withAttr(array $name, \Closure $closure) 动态定义获取器
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
55
 */
4 ignored issues
show
Coding Style introduced by
Missing @category 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...
56
abstract class Model implements JsonSerializable, ArrayAccess
57
{
58
    use model\concern\Attribute;
59
    use model\concern\RelationShip;
60
    use model\concern\ModelEvent;
61
    use model\concern\TimeStamp;
62
    use model\concern\Conversion;
63
64
    /**
65
     * 数据是否存在
66
     * @var bool
67
     */
68
    private $exists = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "exists" must be prefixed with an underscore
Loading history...
69
70
    /**
71
     * 是否强制更新所有数据
72
     * @var bool
73
     */
74
    private $force = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "force" must be prefixed with an underscore
Loading history...
75
76
    /**
77
     * 是否Replace
78
     * @var bool
79
     */
80
    private $replace = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "replace" must be prefixed with an underscore
Loading history...
81
82
    /**
83
     * 数据表后缀
84
     * @var string
85
     */
86
    protected $suffix;
87
88
    /**
89
     * 更新条件
90
     * @var array
91
     */
92
    private $updateWhere;
0 ignored issues
show
Coding Style introduced by
Private member variable "updateWhere" must be prefixed with an underscore
Loading history...
93
94
    /**
95
     * 数据库配置
96
     * @var string
97
     */
98
    protected $connection;
99
100
    /**
101
     * 模型名称
102
     * @var string
103
     */
104
    protected $name;
105
106
    /**
107
     * 数据表名称
108
     * @var string
109
     */
110
    protected $table;
111
112
    /**
113
     * 初始化过的模型.
114
     * @var array
115
     */
116
    protected static $initialized = [];
117
118
    /**
119
     * 查询对象实例
120
     * @var Query
121
     */
122
    protected $queryInstance;
123
124
    /**
125
     * 软删除字段默认值
126
     * @var mixed
127
     */
128
    protected $defaultSoftDelete;
129
130
    /**
131
     * 全局查询范围
132
     * @var array
133
     */
134
    protected $globalScope = [];
135
136
    /**
137
     * 延迟保存信息
138
     * @var bool
139
     */
140
    private $lazySave = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "lazySave" must be prefixed with an underscore
Loading history...
141
142
    /**
143
     * Db对象
144
     * @var Db
145
     */
146
    protected $db;
147
148
    /**
149
     * Event对象
150
     * @var Event
151
     */
152
    protected $event;
153
154
    /**
155
     * 服务注入
156
     * @var Closure
157
     */
158
    protected static $maker;
159
160
    /**
161
     * 设置服务注入
162
     * @access public
163
     * @param Closure $maker
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
164
     * @return void
165
     */
166
    public static function maker(Closure $maker)
167
    {
168
        static::$maker = $maker;
169
    }
170
171
    /**
172
     * 设置Db对象
173
     * @access public
174
     * @param Db $db Db对象
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
175
     * @return void
176
     */
177
    public function setDb(Db $db)
178
    {
179
        $this->db = $db;
180
    }
181
182
    /**
183
     * 设置Event对象
184
     * @access public
185
     * @param Event $event Event对象
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
186
     * @return void
187
     */
188
    public function setEvent(Event $event)
189
    {
190
        $this->event = $event;
191
    }
192
193
    /**
194
     * 设置Connection信息
195
     * @access public
196
     * @param mixed $connection 数据库配置
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
197
     * @return void
198
     */
199
    public function setConnection($connection)
200
    {
201
        $this->connection = $connection;
202
    }
203
204
    /**
205
     * 获取Connection信息
206
     * @access public
207
     * @return string|array
208
     */
209
    public function getConnection()
210
    {
211
        return $this->connection;
212
    }
213
214
    /**
215
     * 架构函数
216
     * @access public
217
     * @param array $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
218
     */
219
    public function __construct(array $data = [])
220
    {
221
        $this->data = $data;
222
223
        if (!empty($this->data)) {
224
            // 废弃字段
225
            foreach ((array) $this->disuse as $key) {
226
                if (array_key_exists($key, $this->data)) {
227
                    unset($this->data[$key]);
228
                }
229
            }
230
        }
231
232
        // 记录原始数据
233
        $this->origin = $this->data;
234
235
        if (empty($this->name)) {
236
            // 当前模型名
237
            $name       = str_replace('\\', '/', static::class);
238
            $this->name = basename($name);
239
        }
240
241
        if (static::$maker) {
242
            call_user_func(static::$maker, $this);
243
        }
244
245
        // 执行初始化操作
246
        $this->initialize();
247
    }
248
249
    /**
250
     * 获取当前模型名称
251
     * @access public
252
     * @return string
253
     */
254
    public function getName(): string
255
    {
256
        return $this->name;
257
    }
258
259
    /**
260
     * 创建新的模型实例
261
     * @access public
262
     * @param array $data  数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
263
     * @param mixed $where 更新条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
264
     * @return Model
265
     */
266
    public function newInstance(array $data = [], $where = null): Model
267
    {
268
        if (empty($data)) {
269
            return new static();
270
        }
271
272
        $model = (new static($data))->exists(true);
273
        $model->setUpdateWhere($where);
274
275
        $model->trigger('AfterRead');
276
277
        return $model;
278
    }
279
280
    /**
281
     * 设置模型的更新条件
282
     * @access protected
283
     * @param mixed $where 更新条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
284
     * @return void
285
     */
286
    protected function setUpdateWhere($where): void
287
    {
288
        $this->updateWhere = $where;
289
    }
290
291
    /**
292
     * 设置当前模型的数据库查询对象
293
     * @access public
294
     * @param Query $query 查询对象实例
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
295
     * @return $this
296
     */
297
    public function setQuery(Query $query)
298
    {
299
        $this->queryInstance = clone $query;
300
        return $this;
301
    }
302
303
    /**
304
     * 设置当前模型数据表的后缀
305
     * @access public
306
     * @param string $suffix 数据表后缀
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
307
     * @return $this
308
     */
309
    public function setSuffix(string $suffix)
310
    {
311
        $this->suffix = $suffix;
312
        return $this;
313
    }
314
315
    /**
316
     * 获取当前模型的数据表后缀
317
     * @access public
318
     * @return string
319
     */
320
    public function getSuffix(): string
321
    {
322
        return $this->suffix ?: '';
323
    }
324
325
    /**
326
     * 获取当前模型的数据库查询对象
327
     * @access public
328
     * @param array|false $scope 使用的全局查询范围
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
329
     * @return Query
330
     */
331
    public function db($scope = []): Query
332
    {
333
        /** @var Query $query */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
334
        if ($this->queryInstance) {
335
            $query = $this->queryInstance->removeOption();
336
        } else {
337
            $query = $this->db->buildQuery($this->connection)
338
                ->name($this->name . $this->suffix)
339
                ->pk($this->pk);
340
        }
341
342
        $query->model($this)
343
            ->json($this->json, $this->jsonAssoc)
344
            ->setFieldType(array_merge($this->schema, $this->jsonType));
345
346
        if (!empty($this->table)) {
347
            $query->table($this->table . $this->suffix);
348
        }
349
350
        // 软删除
351
        if (property_exists($this, 'withTrashed') && !$this->withTrashed) {
0 ignored issues
show
Bug Best Practice introduced by
The property withTrashed does not exist on think\Model. Since you implemented __get, consider adding a @property annotation.
Loading history...
352
            $this->withNoTrashed($query);
0 ignored issues
show
Bug introduced by
The method withNoTrashed() does not exist on think\Model. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

352
            $this->/** @scrutinizer ignore-call */ 
353
                   withNoTrashed($query);
Loading history...
353
        }
354
355
        // 全局作用域
356
        $globalScope = is_array($scope) && !empty($scope) ? $scope : $this->globalScope;
357
358
        if (!empty($globalScope) && false !== $scope) {
359
            $query->scope($globalScope);
360
        }
361
362
        // 返回当前模型的数据库查询对象
363
        return $query;
364
    }
365
366
    /**
367
     *  初始化模型
368
     * @access private
369
     * @return void
370
     */
371
    private function initialize(): void
0 ignored issues
show
Coding Style introduced by
Private method name "Model::initialize" must be prefixed with an underscore
Loading history...
372
    {
373
        if (!isset(static::$initialized[static::class])) {
374
            static::$initialized[static::class] = true;
375
            static::init();
376
        }
377
    }
378
379
    /**
380
     * 初始化处理
381
     * @access protected
382
     * @return void
383
     */
384
    protected static function init()
385
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
386
387
    protected function checkData(): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function checkData()
Loading history...
388
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
389
390
    protected function checkResult($result): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function checkResult()
Loading history...
391
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
392
393
    /**
394
     * 更新是否强制写入数据 而不做比较
395
     * @access public
396
     * @param bool $force
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
397
     * @return $this
398
     */
399
    public function force(bool $force = true)
400
    {
401
        $this->force = $force;
402
        return $this;
403
    }
404
405
    /**
406
     * 判断force
407
     * @access public
408
     * @return bool
409
     */
410
    public function isForce(): bool
411
    {
412
        return $this->force;
413
    }
414
415
    /**
416
     * 新增数据是否使用Replace
417
     * @access public
418
     * @param bool $replace
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
419
     * @return $this
420
     */
421
    public function replace(bool $replace = true)
422
    {
423
        $this->replace = $replace;
424
        return $this;
425
    }
426
427
    /**
428
     * 刷新模型数据
429
     * @access public
430
     * @param bool $relation 是否刷新关联数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
431
     * @return $this
432
     */
433
    public function refresh(bool $relation = false)
434
    {
435
        if ($this->exists) {
436
            $this->data   = $this->db()->fetchArray()->find($this->getKey());
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db()->fetchArray()->find($this->getKey()) of type think\Model is incompatible with the declared type array of property $data.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
437
            $this->origin = $this->data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->data of type think\Model is incompatible with the declared type array of property $origin.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
438
439
            if ($relation) {
440
                $this->relation = [];
441
            }
442
        }
443
444
        return $this;
445
    }
446
447
    /**
448
     * 设置数据是否存在
449
     * @access public
450
     * @param bool $exists
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
451
     * @return $this
452
     */
453
    public function exists(bool $exists = true)
454
    {
455
        $this->exists = $exists;
456
        return $this;
457
    }
458
459
    /**
460
     * 判断数据是否存在数据库
461
     * @access public
462
     * @return bool
463
     */
464
    public function isExists(): bool
465
    {
466
        return $this->exists;
467
    }
468
469
    /**
470
     * 判断模型是否为空
471
     * @access public
472
     * @return bool
473
     */
474
    public function isEmpty(): bool
475
    {
476
        return empty($this->data);
477
    }
478
479
    /**
480
     * 延迟保存当前数据对象
481
     * @access public
482
     * @param array|bool $data 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
483
     * @return void
484
     */
485
    public function lazySave($data = []): void
486
    {
487
        if (false === $data) {
488
            $this->lazySave = false;
489
        } else {
490
            if (is_array($data)) {
491
                $this->setAttrs($data);
492
            }
493
494
            $this->lazySave = true;
495
        }
496
    }
497
498
    /**
499
     * 保存当前数据对象
500
     * @access public
501
     * @param array  $data     数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
502
     * @param string $sequence 自增序列名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
503
     * @return bool
504
     */
505
    public function save(array $data = [], string $sequence = null): bool
506
    {
507
        // 数据对象赋值
508
        $this->setAttrs($data);
509
510
        if ($this->isEmpty() || false === $this->trigger('BeforeWrite')) {
511
            return false;
512
        }
513
514
        $result = $this->exists ? $this->updateData() : $this->insertData($sequence);
515
516
        if (false === $result) {
517
            return false;
518
        }
519
520
        // 写入回调
521
        $this->trigger('AfterWrite');
522
523
        // 重新记录原始数据
524
        $this->origin   = $this->data;
525
        $this->set      = [];
526
        $this->lazySave = false;
527
528
        return true;
529
    }
530
531
    /**
532
     * 检查数据是否允许写入
533
     * @access protected
534
     * @return array
535
     */
536
    protected function checkAllowFields(): array
537
    {
538
        // 检测字段
539
        if (empty($this->field)) {
540
            if (!empty($this->schema)) {
541
                $this->field = array_keys(array_merge($this->schema, $this->jsonType));
542
            } else {
543
                $query = $this->db();
544
                $table = $this->table ? $this->table . $this->suffix : $query->getTable();
545
546
                $this->field = $query->getConnection()->getTableFields($table);
547
            }
548
549
            return $this->field;
550
        }
551
552
        $field = $this->field;
553
554
        if ($this->autoWriteTimestamp) {
555
            array_push($field, $this->createTime, $this->updateTime);
556
        }
557
558
        if (!empty($this->disuse)) {
559
            // 废弃字段
560
            $field = array_diff($field, $this->disuse);
561
        }
562
563
        return $field;
564
    }
565
566
    /**
567
     * 保存写入数据
568
     * @access protected
569
     * @return bool
570
     */
571
    protected function updateData(): bool
572
    {
573
        // 事件回调
574
        if (false === $this->trigger('BeforeUpdate')) {
575
            return false;
576
        }
577
578
        $this->checkData();
579
580
        // 获取有更新的数据
581
        $data = $this->getChangedData();
582
583
        if (empty($data)) {
584
            // 关联更新
585
            if (!empty($this->relationWrite)) {
586
                $this->autoRelationUpdate();
587
            }
588
589
            return true;
590
        }
591
592
        if ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) {
593
            // 自动写入更新时间
594
            $data[$this->updateTime]       = $this->autoWriteTimestamp($this->updateTime);
0 ignored issues
show
Bug introduced by
It seems like $this->updateTime can also be of type true; however, parameter $name of think\Model::autoWriteTimestamp() 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

594
            $data[$this->updateTime]       = $this->autoWriteTimestamp(/** @scrutinizer ignore-type */ $this->updateTime);
Loading history...
595
            $this->data[$this->updateTime] = $data[$this->updateTime];
596
        }
597
598
        // 检查允许字段
599
        $allowFields = $this->checkAllowFields();
600
601
        foreach ($this->relationWrite as $name => $val) {
602
            if (!is_array($val)) {
603
                continue;
604
            }
605
606
            foreach ($val as $key) {
607
                if (isset($data[$key])) {
608
                    unset($data[$key]);
609
                }
610
            }
611
        }
612
613
        // 模型更新
614
        $db = $this->db();
615
        $db->startTrans();
616
617
        try {
618
            $where  = $this->getWhere();
619
            $result = $db->where($where)
620
                ->strict(false)
621
                ->field($allowFields)
622
                ->update($data);
623
624
            $this->checkResult($result);
625
626
            // 关联更新
627
            if (!empty($this->relationWrite)) {
628
                $this->autoRelationUpdate();
629
            }
630
631
            $db->commit();
632
633
            // 更新回调
634
            $this->trigger('AfterUpdate');
635
636
            return true;
637
        } catch (\Exception $e) {
638
            $db->rollback();
639
            throw $e;
640
        }
641
    }
642
643
    /**
644
     * 新增写入数据
645
     * @access protected
646
     * @param string $sequence 自增名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
647
     * @return bool
648
     */
649
    protected function insertData(string $sequence = null): bool
650
    {
651
        // 时间戳自动写入
652
        if ($this->autoWriteTimestamp) {
653
            if ($this->createTime && !isset($this->data[$this->createTime])) {
654
                $this->data[$this->createTime] = $this->autoWriteTimestamp($this->createTime);
0 ignored issues
show
Bug introduced by
It seems like $this->createTime can also be of type true; however, parameter $name of think\Model::autoWriteTimestamp() 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

654
                $this->data[$this->createTime] = $this->autoWriteTimestamp(/** @scrutinizer ignore-type */ $this->createTime);
Loading history...
655
            }
656
657
            if ($this->updateTime && !isset($this->data[$this->updateTime])) {
658
                $this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
659
            }
660
        }
661
662
        if (false === $this->trigger('BeforeInsert')) {
663
            return false;
664
        }
665
666
        $this->checkData();
667
668
        // 检查允许字段
669
        $allowFields = $this->checkAllowFields();
670
671
        $db = $this->db();
672
        $db->startTrans();
673
674
        try {
675
            $result = $db->strict(false)
676
                ->field($allowFields)
677
                ->replace($this->replace)
678
                ->insert($this->data, false, $sequence);
0 ignored issues
show
Unused Code introduced by
The call to think\db\Query::insert() has too many arguments starting with $sequence. ( Ignorable by Annotation )

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

678
                ->/** @scrutinizer ignore-call */ insert($this->data, false, $sequence);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
679
680
            // 获取自动增长主键
681
            if ($result && $insertId = $db->getLastInsID($sequence)) {
682
                $pk = $this->getPk();
683
684
                foreach ((array) $pk as $key) {
685
                    if (!isset($this->data[$key]) || '' == $this->data[$key]) {
686
                        $this->data[$key] = $insertId;
687
                    }
688
                }
689
            }
690
691
            // 关联写入
692
            if (!empty($this->relationWrite)) {
693
                $this->autoRelationInsert();
694
            }
695
696
            $db->commit();
697
698
            // 标记数据已经存在
699
            $this->exists = true;
700
701
            // 新增回调
702
            $this->trigger('AfterInsert');
703
704
            return true;
705
        } catch (\Exception $e) {
706
            $db->rollback();
707
            throw $e;
708
        }
709
    }
710
711
    /**
712
     * 获取当前的更新条件
713
     * @access public
714
     * @return mixed
715
     */
716
    public function getWhere()
717
    {
718
        $pk = $this->getPk();
719
720
        if (is_string($pk) && isset($this->data[$pk])) {
721
            $where = [[$pk, '=', $this->data[$pk]]];
722
        } elseif (!empty($this->updateWhere)) {
723
            $where = $this->updateWhere;
724
        } else {
725
            $where = null;
726
        }
727
728
        return $where;
729
    }
730
731
    /**
732
     * 保存多个数据到当前数据对象
733
     * @access public
734
     * @param iterable $dataSet 数据
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
735
     * @param boolean  $replace 是否自动识别更新和写入
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
736
     * @return Collection
737
     * @throws \Exception
738
     */
739
    public function saveAll(iterable $dataSet, bool $replace = true): Collection
740
    {
741
        $db = $this->db();
742
        $db->startTrans();
743
744
        try {
745
            $pk = $this->getPk();
746
747
            if (is_string($pk) && $replace) {
748
                $auto = true;
749
            }
750
751
            $result = [];
752
753
            foreach ($dataSet as $key => $data) {
754
                if ($this->exists || (!empty($auto) && isset($data[$pk]))) {
755
                    $result[$key] = self::update($data, $this->field);
756
                } else {
757
                    $result[$key] = self::create($data, $this->field, $this->replace);
758
                }
759
            }
760
761
            $db->commit();
762
763
            return $this->toCollection($result);
764
        } catch (\Exception $e) {
765
            $db->rollback();
766
            throw $e;
767
        }
768
    }
769
770
    /**
771
     * 删除当前的记录
772
     * @access public
773
     * @return bool
774
     */
775
    public function delete(): bool
776
    {
777
        if (!$this->exists || $this->isEmpty() || false === $this->trigger('BeforeDelete')) {
778
            return false;
779
        }
780
781
        // 读取更新条件
782
        $where = $this->getWhere();
783
784
        $db = $this->db();
785
        $db->startTrans();
786
787
        try {
788
            // 删除当前模型数据
789
            $db->where($where)->delete();
790
791
            // 关联删除
792
            if (!empty($this->relationWrite)) {
793
                $this->autoRelationDelete();
794
            }
795
796
            $db->commit();
797
798
            $this->trigger('AfterDelete');
799
800
            $this->exists   = false;
801
            $this->lazySave = false;
802
803
            return true;
804
        } catch (\Exception $e) {
805
            $db->rollback();
806
            throw $e;
807
        }
808
    }
809
810
    /**
811
     * 写入数据
812
     * @access public
813
     * @param array $data       数据数组
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
814
     * @param array $allowField 允许字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
815
     * @param bool  $replace    使用Replace
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
816
     * @return static
817
     */
818
    public static function create(array $data, array $allowField = [], bool $replace = false): Model
819
    {
820
        $model = new static();
821
822
        if (!empty($allowField)) {
823
            $model->allowField($allowField);
824
        }
825
826
        $model->replace($replace)->save($data);
827
828
        return $model;
829
    }
830
831
    /**
832
     * 更新数据
833
     * @access public
834
     * @param array $data       数据数组
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
835
     * @param mixed $where      更新条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
836
     * @param array $allowField 允许字段
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
837
     * @return static
838
     */
839
    public static function update(array $data, $where = [], array $allowField = [])
840
    {
841
        $model = new static();
842
843
        if (!empty($allowField)) {
844
            $model->allowField($allowField);
845
        }
846
847
        if (!empty($where)) {
848
            $model->setUpdateWhere($where);
849
        }
850
851
        $model->exists(true)->save($data);
852
853
        return $model;
854
    }
855
856
    /**
857
     * 删除记录
858
     * @access public
859
     * @param mixed $data  主键列表 支持闭包查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
860
     * @param bool  $force 是否强制删除
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
861
     * @return bool
862
     */
863
    public static function destroy($data, bool $force = false): bool
864
    {
865
        if (empty($data) && 0 !== $data) {
866
            return false;
867
        }
868
869
        $model = new static();
870
871
        $query = $model->db();
872
873
        if (is_array($data) && key($data) !== 0) {
874
            $query->where($data);
875
            $data = null;
876
        } elseif ($data instanceof \Closure) {
877
            $data($query);
878
            $data = null;
879
        }
880
881
        $resultSet = $query->select($data);
882
883
        foreach ($resultSet as $result) {
884
            $result->force($force)->delete();
885
        }
886
887
        return true;
888
    }
889
890
    /**
891
     * 解序列化后处理
892
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
893
    public function __wakeup()
894
    {
895
        $this->initialize();
896
    }
897
898
    public function __debugInfo()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __debugInfo()
Loading history...
899
    {
900
        return [
901
            'data'     => $this->data,
902
            'relation' => $this->relation,
903
        ];
904
    }
905
906
    /**
907
     * 修改器 设置数据对象的值
908
     * @access public
909
     * @param string $name  名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
910
     * @param mixed  $value 值
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
911
     * @return void
912
     */
913
    public function __set(string $name, $value): void
914
    {
915
        $this->setAttr($name, $value);
916
    }
917
918
    /**
919
     * 获取器 获取数据对象的值
920
     * @access public
921
     * @param string $name 名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
922
     * @return mixed
923
     */
924
    public function __get(string $name)
925
    {
926
        return $this->getAttr($name);
927
    }
928
929
    /**
930
     * 检测数据对象的值
931
     * @access public
932
     * @param string $name 名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
933
     * @return bool
934
     */
935
    public function __isset(string $name): bool
936
    {
937
        return !is_null($this->getAttr($name));
938
    }
939
940
    /**
941
     * 销毁数据对象的值
942
     * @access public
943
     * @param string $name 名称
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
944
     * @return void
945
     */
946
    public function __unset(string $name): void
947
    {
948
        unset($this->data[$name], $this->relation[$name]);
949
    }
950
951
    // ArrayAccess
952
    public function offsetSet($name, $value)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
953
    {
954
        $this->setAttr($name, $value);
955
    }
956
957
    public function offsetExists($name): bool
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function offsetExists()
Loading history...
958
    {
959
        return $this->__isset($name);
960
    }
961
962
    public function offsetUnset($name)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function offsetUnset()
Loading history...
963
    {
964
        $this->__unset($name);
965
    }
966
967
    public function offsetGet($name)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function offsetGet()
Loading history...
968
    {
969
        return $this->getAttr($name);
970
    }
971
972
    /**
973
     * 设置使用的全局查询范围
974
     * @access public
975
     * @param array|false $scope 启用的全局查询范围
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
976
     * @return Query
977
     */
978
    public static function useGlobalScope($scope)
979
    {
980
        $model = new static();
981
982
        return $model->db($scope);
983
    }
984
985
    /**
986
     * 切换后缀进行查询
987
     * @access public
988
     * @param string $suffix 切换的表后缀
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
989
     * @return Model
990
     */
991
    public static function change(string $suffix)
992
    {
993
        $model = new static();
994
        $model->setSuffix($suffix);
995
996
        return $model;
997
    }
998
999
    public function __call($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __call()
Loading history...
1000
    {
1001
        if ('withattr' == strtolower($method)) {
1002
            return call_user_func_array([$this, 'withAttribute'], $args);
1003
        }
1004
1005
        return call_user_func_array([$this->db(), $method], $args);
1006
    }
1007
1008
    public static function __callStatic($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __callStatic()
Loading history...
1009
    {
1010
        $model = new static();
1011
1012
        return call_user_func_array([$model->db(), $method], $args);
1013
    }
1014
1015
    /**
1016
     * 析构方法
1017
     * @access public
1018
     */
1019
    public function __destruct()
1020
    {
1021
        if ($this->lazySave) {
1022
            $this->save();
1023
        }
1024
    }
1025
}
1026