Completed
Push — 6.0 ( 33b795...b1ea4f )
by liu
18:12 queued 14:12
created

Model::checkData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 2
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 void onAfterRead(Model $model) static after_read事件定义
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 mixed onBeforeInsert(Model $model) static before_insert事件定义
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 void onAfterInsert(Model $model) static after_insert事件定义
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 mixed onBeforeUpdate(Model $model) static before_update事件定义
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 void onAfterUpdate(Model $model) static after_update事件定义
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 mixed onBeforeWrite(Model $model) static before_write事件定义
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 void onAfterWrite(Model $model) static after_write事件定义
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 mixed onBeforeDelete(Model $model) static before_write事件定义
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 void onAfterDelete(Model $model) static after_delete事件定义
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 void onBeforeRestore(Model $model) static before_restore事件定义
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 void onAfterRestore(Model $model) static after_restore事件定义
1 ignored issue
show
Coding Style introduced by
Tag value for @method tag indented incorrectly; expected 2 spaces but found 1
Loading history...
35
 */
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...
36
abstract class Model implements JsonSerializable, ArrayAccess
37
{
38
    use model\concern\Attribute;
39
    use model\concern\RelationShip;
40
    use model\concern\ModelEvent;
41
    use model\concern\TimeStamp;
42
    use model\concern\Conversion;
43
44
    /**
45
     * 数据是否存在
46
     * @var bool
47
     */
48
    private $exists = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "exists" must be prefixed with an underscore
Loading history...
49
50
    /**
51
     * 是否强制更新所有数据
52
     * @var bool
53
     */
54
    private $force = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "force" must be prefixed with an underscore
Loading history...
55
56
    /**
57
     * 是否Replace
58
     * @var bool
59
     */
60
    private $replace = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "replace" must be prefixed with an underscore
Loading history...
61
62
    /**
63
     * 数据表后缀
64
     * @var string
65
     */
66
    protected $suffix;
67
68
    /**
69
     * 更新条件
70
     * @var array
71
     */
72
    private $updateWhere;
0 ignored issues
show
Coding Style introduced by
Private member variable "updateWhere" must be prefixed with an underscore
Loading history...
73
74
    /**
75
     * 数据库配置
76
     * @var string
77
     */
78
    protected $connection;
79
80
    /**
81
     * 模型名称
82
     * @var string
83
     */
84
    protected $name;
85
86
    /**
87
     * 数据表名称
88
     * @var string
89
     */
90
    protected $table;
91
92
    /**
93
     * 初始化过的模型.
94
     * @var array
95
     */
96
    protected static $initialized = [];
97
98
    /**
99
     * 查询对象实例
100
     * @var Query
101
     */
102
    protected $queryInstance;
103
104
    /**
105
     * 软删除字段默认值
106
     * @var mixed
107
     */
108
    protected $defaultSoftDelete;
109
110
    /**
111
     * 全局查询范围
112
     * @var array
113
     */
114
    protected $globalScope = [];
115
116
    /**
117
     * 延迟保存信息
118
     * @var bool
119
     */
120
    private $lazySave = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "lazySave" must be prefixed with an underscore
Loading history...
121
122
    /**
123
     * Db对象
124
     * @var Db
125
     */
126
    protected $db;
127
128
    /**
129
     * Event对象
130
     * @var Event
131
     */
132
    protected $event;
133
134
    /**
135
     * 服务注入
136
     * @var Closure
137
     */
138
    protected static $maker;
139
140
    /**
141
     * 设置服务注入
142
     * @access public
143
     * @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...
144
     * @return void
145
     */
146
    public static function maker(Closure $maker)
147
    {
148
        static::$maker = $maker;
149
    }
150
151
    /**
152
     * 设置Db对象
153
     * @access public
154
     * @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...
155
     * @return void
156
     */
157
    public function setDb(Db $db)
158
    {
159
        $this->db = $db;
160
    }
161
162
    /**
163
     * 设置Event对象
164
     * @access public
165
     * @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...
166
     * @return void
167
     */
168
    public function setEvent(Event $event)
169
    {
170
        $this->event = $event;
171
    }
172
173
    /**
174
     * 设置Connection信息
175
     * @access public
176
     * @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...
177
     * @return void
178
     */
179
    public function setConnection($connection)
180
    {
181
        $this->connection = $connection;
182
    }
183
184
    /**
185
     * 获取Connection信息
186
     * @access public
187
     * @return string|array
188
     */
189
    public function getConnection()
190
    {
191
        return $this->connection;
192
    }
193
194
    /**
195
     * 架构函数
196
     * @access public
197
     * @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...
198
     */
199
    public function __construct(array $data = [])
200
    {
201
        $this->data = $data;
202
203
        if (!empty($this->data)) {
204
            // 废弃字段
205
            foreach ((array) $this->disuse as $key) {
206
                if (array_key_exists($key, $this->data)) {
207
                    unset($this->data[$key]);
208
                }
209
            }
210
        }
211
212
        // 记录原始数据
213
        $this->origin = $this->data;
214
215
        if (empty($this->name)) {
216
            // 当前模型名
217
            $name       = str_replace('\\', '/', static::class);
218
            $this->name = basename($name);
219
        }
220
221
        if (static::$maker) {
222
            call_user_func(static::$maker, $this);
223
        }
224
225
        // 执行初始化操作
226
        $this->initialize();
227
    }
228
229
    /**
230
     * 获取当前模型名称
231
     * @access public
232
     * @return string
233
     */
234
    public function getName(): string
235
    {
236
        return $this->name;
237
    }
238
239
    /**
240
     * 创建新的模型实例
241
     * @access public
242
     * @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...
243
     * @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...
244
     * @return Model
245
     */
246
    public function newInstance(array $data = [], $where = null): Model
247
    {
248
        if (empty($data)) {
249
            return new static();
250
        }
251
252
        $model = (new static($data))->exists(true);
253
        $model->setUpdateWhere($where);
254
255
        $model->trigger('AfterRead');
256
257
        return $model;
258
    }
259
260
    /**
261
     * 设置模型的更新条件
262
     * @access protected
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 void
265
     */
266
    protected function setUpdateWhere($where): void
267
    {
268
        $this->updateWhere = $where;
269
    }
270
271
    /**
272
     * 设置当前模型的数据库查询对象
273
     * @access public
274
     * @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...
275
     * @param bool  $clear 是否需要清空查询条件
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
276
     * @return $this
277
     */
278
    public function setQuery(Query $query, bool $clear = true)
279
    {
280
        $this->queryInstance = clone $query;
281
282
        if ($clear) {
283
            $this->queryInstance->removeOption();
284
        }
285
286
        return $this;
287
    }
288
289
    /**
290
     * 设置当前模型数据表的后缀
291
     * @access public
292
     * @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...
293
     * @return $this
294
     */
295
    public function setSuffix(string $suffix)
296
    {
297
        $this->suffix = $suffix;
298
        return $this;
299
    }
300
301
    /**
302
     * 获取当前模型的数据表后缀
303
     * @access public
304
     * @return string
305
     */
306
    public function getSuffix(): string
307
    {
308
        return $this->suffix ?: '';
309
    }
310
311
    /**
312
     * 获取当前模型的数据库查询对象
313
     * @access public
314
     * @param array $scope 设置不使用的全局查询范围
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
315
     * @return Query
316
     */
317
    public function db($scope = []): Query
318
    {
319
        /** @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...
320
        if ($this->queryInstance) {
321
            $query = $this->queryInstance;
322
        } else {
323
            $query = $this->db->buildQuery($this->connection)
324
                ->name($this->name . $this->suffix)
325
                ->pk($this->pk);
326
327
            if (!empty($this->table)) {
328
                $query->table($this->table . $this->suffix);
329
            }
330
        }
331
332
        $query->model($this)
333
            ->json($this->json, $this->jsonAssoc)
334
            ->setFieldType(array_merge($this->schema, $this->jsonType));
335
336
        // 软删除
337
        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...
338
            $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

338
            $this->/** @scrutinizer ignore-call */ 
339
                   withNoTrashed($query);
Loading history...
339
        }
340
341
        // 全局作用域
342
        if (is_array($scope)) {
0 ignored issues
show
introduced by
The condition is_array($scope) is always true.
Loading history...
343
            $globalScope = array_diff($this->globalScope, $scope);
344
            $query->scope($globalScope);
345
        }
346
347
        // 返回当前模型的数据库查询对象
348
        return $query;
349
    }
350
351
    /**
352
     *  初始化模型
353
     * @access private
354
     * @return void
355
     */
356
    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...
357
    {
358
        if (!isset(static::$initialized[static::class])) {
359
            static::$initialized[static::class] = true;
360
            static::init();
361
        }
362
    }
363
364
    /**
365
     * 初始化处理
366
     * @access protected
367
     * @return void
368
     */
369
    protected static function init()
370
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
371
372
    protected function checkData(): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function checkData()
Loading history...
373
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
374
375
    protected function checkResult($result): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function checkResult()
Loading history...
376
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
377
378
    /**
379
     * 更新是否强制写入数据 而不做比较
380
     * @access public
381
     * @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...
382
     * @return $this
383
     */
384
    public function force(bool $force = true)
385
    {
386
        $this->force = $force;
387
        return $this;
388
    }
389
390
    /**
391
     * 判断force
392
     * @access public
393
     * @return bool
394
     */
395
    public function isForce(): bool
396
    {
397
        return $this->force;
398
    }
399
400
    /**
401
     * 新增数据是否使用Replace
402
     * @access public
403
     * @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...
404
     * @return $this
405
     */
406
    public function replace(bool $replace = true)
407
    {
408
        $this->replace = $replace;
409
        return $this;
410
    }
411
412
    /**
413
     * 刷新模型数据
414
     * @access public
415
     * @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...
416
     * @return $this
417
     */
418
    public function refresh(bool $relation = false)
419
    {
420
        if ($this->exists) {
421
            $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...
422
            $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...
423
424
            if ($relation) {
425
                $this->relation = [];
426
            }
427
        }
428
429
        return $this;
430
    }
431
432
    /**
433
     * 设置数据是否存在
434
     * @access public
435
     * @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...
436
     * @return $this
437
     */
438
    public function exists(bool $exists = true)
439
    {
440
        $this->exists = $exists;
441
        return $this;
442
    }
443
444
    /**
445
     * 判断数据是否存在数据库
446
     * @access public
447
     * @return bool
448
     */
449
    public function isExists(): bool
450
    {
451
        return $this->exists;
452
    }
453
454
    /**
455
     * 判断模型是否为空
456
     * @access public
457
     * @return bool
458
     */
459
    public function isEmpty(): bool
460
    {
461
        return empty($this->data);
462
    }
463
464
    /**
465
     * 延迟保存当前数据对象
466
     * @access public
467
     * @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...
468
     * @return void
469
     */
470
    public function lazySave($data = []): void
471
    {
472
        if (false === $data) {
473
            $this->lazySave = false;
474
        } else {
475
            if (is_array($data)) {
476
                $this->setAttrs($data);
477
            }
478
479
            $this->lazySave = true;
480
        }
481
    }
482
483
    /**
484
     * 保存当前数据对象
485
     * @access public
486
     * @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...
487
     * @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...
488
     * @return bool
489
     */
490
    public function save(array $data = [], string $sequence = null): bool
491
    {
492
        // 数据对象赋值
493
        $this->setAttrs($data);
494
495
        if ($this->isEmpty() || false === $this->trigger('BeforeWrite')) {
496
            return false;
497
        }
498
499
        $result = $this->exists ? $this->updateData() : $this->insertData($sequence);
500
501
        if (false === $result) {
502
            return false;
503
        }
504
505
        // 写入回调
506
        $this->trigger('AfterWrite');
507
508
        // 重新记录原始数据
509
        $this->origin   = $this->data;
510
        $this->set      = [];
511
        $this->lazySave = false;
512
513
        return true;
514
    }
515
516
    /**
517
     * 检查数据是否允许写入
518
     * @access protected
519
     * @return array
520
     */
521
    protected function checkAllowFields(): array
522
    {
523
        // 检测字段
524
        if (empty($this->field)) {
525
            if (!empty($this->schema)) {
526
                $this->field = array_keys(array_merge($this->schema, $this->jsonType));
527
            } else {
528
                $query = $this->db();
529
                $table = $this->table ? $this->table . $this->suffix : $query->getTable();
530
531
                $this->field = $query->getConnection()->getTableFields($table);
532
            }
533
534
            return $this->field;
535
        }
536
537
        $field = $this->field;
538
539
        if ($this->autoWriteTimestamp) {
540
            array_push($field, $this->createTime, $this->updateTime);
541
        }
542
543
        if (!empty($this->disuse)) {
544
            // 废弃字段
545
            $field = array_diff($field, $this->disuse);
546
        }
547
548
        return $field;
549
    }
550
551
    /**
552
     * 保存写入数据
553
     * @access protected
554
     * @return bool
555
     */
556
    protected function updateData(): bool
557
    {
558
        // 事件回调
559
        if (false === $this->trigger('BeforeUpdate')) {
560
            return false;
561
        }
562
563
        $this->checkData();
564
565
        // 获取有更新的数据
566
        $data = $this->getChangedData();
567
568
        if (empty($data)) {
569
            // 关联更新
570
            if (!empty($this->relationWrite)) {
571
                $this->autoRelationUpdate();
572
            }
573
574
            return true;
575
        }
576
577
        if ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) {
578
            // 自动写入更新时间
579
            $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

579
            $data[$this->updateTime]       = $this->autoWriteTimestamp(/** @scrutinizer ignore-type */ $this->updateTime);
Loading history...
580
            $this->data[$this->updateTime] = $data[$this->updateTime];
581
        }
582
583
        // 检查允许字段
584
        $allowFields = $this->checkAllowFields();
585
586
        foreach ($this->relationWrite as $name => $val) {
587
            if (!is_array($val)) {
588
                continue;
589
            }
590
591
            foreach ($val as $key) {
592
                if (isset($data[$key])) {
593
                    unset($data[$key]);
594
                }
595
            }
596
        }
597
598
        // 模型更新
599
        $db = $this->db();
600
        $db->startTrans();
601
602
        try {
603
            $where  = $this->getWhere();
604
            $result = $db->where($where)
605
                ->strict(false)
606
                ->field($allowFields)
607
                ->update($data);
608
609
            $this->checkResult($result);
610
611
            // 关联更新
612
            if (!empty($this->relationWrite)) {
613
                $this->autoRelationUpdate();
614
            }
615
616
            $db->commit();
617
618
            // 更新回调
619
            $this->trigger('AfterUpdate');
620
621
            return true;
622
        } catch (\Exception $e) {
623
            $db->rollback();
624
            throw $e;
625
        }
626
    }
627
628
    /**
629
     * 新增写入数据
630
     * @access protected
631
     * @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...
632
     * @return bool
633
     */
634
    protected function insertData(string $sequence = null): bool
635
    {
636
        // 时间戳自动写入
637
        if ($this->autoWriteTimestamp) {
638
            if ($this->createTime && !isset($this->data[$this->createTime])) {
639
                $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

639
                $this->data[$this->createTime] = $this->autoWriteTimestamp(/** @scrutinizer ignore-type */ $this->createTime);
Loading history...
640
            }
641
642
            if ($this->updateTime && !isset($this->data[$this->updateTime])) {
643
                $this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
644
            }
645
        }
646
647
        if (false === $this->trigger('BeforeInsert')) {
648
            return false;
649
        }
650
651
        $this->checkData();
652
653
        // 检查允许字段
654
        $allowFields = $this->checkAllowFields();
655
656
        $db = $this->db();
657
        $db->startTrans();
658
659
        try {
660
            $result = $db->strict(false)
661
                ->field($allowFields)
662
                ->replace($this->replace)
663
                ->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

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