Completed
Push — 6.0 ( 19ddff...f9d161 )
by liu
03:04
created

Model::useGlobalScope()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 3
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
     * @return $this
276
     */
277
    public function setQuery(Query $query)
278
    {
279
        $this->queryInstance = clone $query;
280
        return $this;
281
    }
282
283
    /**
284
     * 设置当前模型数据表的后缀
285
     * @access public
286
     * @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...
287
     * @return $this
288
     */
289
    public function setSuffix(string $suffix)
290
    {
291
        $this->suffix = $suffix;
292
        return $this;
293
    }
294
295
    /**
296
     * 获取当前模型的数据表后缀
297
     * @access public
298
     * @return string
299
     */
300
    public function getSuffix(): string
301
    {
302
        return $this->suffix ?: '';
303
    }
304
305
    /**
306
     * 获取当前模型的数据库查询对象
307
     * @access public
308
     * @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...
309
     * @return Query
310
     */
311
    public function db($scope = []): Query
312
    {
313
        /** @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...
314
        if ($this->queryInstance) {
315
            $query = $this->queryInstance->removeOption();
316
        } else {
317
            $query = $this->db->buildQuery($this->connection)
318
                ->name($this->name . $this->suffix)
319
                ->pk($this->pk);
320
        }
321
322
        $query->model($this)
323
            ->json($this->json, $this->jsonAssoc)
324
            ->setFieldType(array_merge($this->schema, $this->jsonType));
325
326
        if (!empty($this->table)) {
327
            $query->table($this->table . $this->suffix);
328
        }
329
330
        // 软删除
331
        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...
332
            $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

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

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

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

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