Completed
Push — 6.0 ( a5dd93...c6d21a )
by liu
24:37 queued 15:38
created

Model::setConnection()   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 1
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 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
     * 架构函数
175
     * @access public
176
     * @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...
177
     */
178
    public function __construct(array $data = [])
179
    {
180
        $this->data = $data;
181
182
        if (!empty($this->data)) {
183
            // 废弃字段
184
            foreach ((array) $this->disuse as $key) {
185
                if (array_key_exists($key, $this->data)) {
186
                    unset($this->data[$key]);
187
                }
188
            }
189
        }
190
191
        // 记录原始数据
192
        $this->origin = $this->data;
193
194
        if (empty($this->name)) {
195
            // 当前模型名
196
            $name       = str_replace('\\', '/', static::class);
197
            $this->name = basename($name);
198
        }
199
200
        if (static::$maker) {
201
            call_user_func(static::$maker, $this);
202
        }
203
204
        // 执行初始化操作
205
        $this->initialize();
206
    }
207
208
    /**
209
     * 获取当前模型名称
210
     * @access public
211
     * @return string
212
     */
213
    public function getName(): string
214
    {
215
        return $this->name;
216
    }
217
218
    /**
219
     * 创建新的模型实例
220
     * @access public
221
     * @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...
222
     * @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...
223
     * @return Model
224
     */
225
    public function newInstance(array $data = [], $where = null): Model
226
    {
227
        if (empty($data)) {
228
            return new static();
229
        }
230
231
        $model = (new static($data))->exists(true);
232
        $model->setUpdateWhere($where);
233
234
        $model->trigger('AfterRead');
235
236
        return $model;
237
    }
238
239
    /**
240
     * 设置模型的更新条件
241
     * @access protected
242
     * @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...
243
     * @return void
244
     */
245
    protected function setUpdateWhere($where): void
246
    {
247
        $this->updateWhere = $where;
248
    }
249
250
    /**
251
     * 设置当前模型的数据库查询对象
252
     * @access public
253
     * @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...
254
     * @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...
255
     * @return $this
256
     */
257
    public function setQuery(Query $query, bool $clear = true)
258
    {
259
        $this->queryInstance = clone $query;
260
261
        if ($clear) {
262
            $this->queryInstance->removeOption();
263
        }
264
265
        return $this;
266
    }
267
268
    /**
269
     * 获取当前模型的数据库查询对象
270
     * @access public
271
     * @return Query|null
272
     */
273
    public function getQuery()
274
    {
275
        return $this->queryInstance;
276
    }
277
278
    /**
279
     * 设置当前模型数据表的后缀
280
     * @access public
281
     * @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...
282
     * @return $this
283
     */
284
    public function setSuffix(string $suffix)
285
    {
286
        $this->suffix = $suffix;
287
        return $this;
288
    }
289
290
    /**
291
     * 获取当前模型的数据表后缀
292
     * @access public
293
     * @return string
294
     */
295
    public function getSuffix(): string
296
    {
297
        return $this->suffix ?: '';
298
    }
299
300
    /**
301
     * 获取当前模型的数据库查询对象
302
     * @access public
303
     * @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...
304
     * @return Query
305
     */
306
    public function db($scope = []): Query
307
    {
308
        /** @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...
309
        if ($this->queryInstance) {
310
            $query = $this->queryInstance;
311
        } else {
312
            $query = $this->db->buildQuery($this->connection)
313
                ->name($this->name . $this->suffix)
314
                ->pk($this->pk);
0 ignored issues
show
Bug introduced by
It seems like $this->pk can also be of type array; however, parameter $pk of think\db\Query::pk() 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

314
                ->pk(/** @scrutinizer ignore-type */ $this->pk);
Loading history...
315
316
            if (!empty($this->table)) {
317
                $query->table($this->table . $this->suffix);
318
            }
319
        }
320
321
        $query->model($this)
322
            ->json($this->json, $this->jsonAssoc)
323
            ->setFieldType(array_merge($this->schema, $this->jsonType));
324
325
        // 软删除
326
        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...
327
            $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

327
            $this->/** @scrutinizer ignore-call */ 
328
                   withNoTrashed($query);
Loading history...
328
        }
329
330
        // 全局作用域
331
        if (is_array($scope)) {
0 ignored issues
show
introduced by
The condition is_array($scope) is always true.
Loading history...
332
            $globalScope = array_diff($this->globalScope, $scope);
333
            $query->scope($globalScope);
334
        }
335
336
        // 返回当前模型的数据库查询对象
337
        return $query;
338
    }
339
340
    /**
341
     *  初始化模型
342
     * @access private
343
     * @return void
344
     */
345
    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...
346
    {
347
        if (!isset(static::$initialized[static::class])) {
348
            static::$initialized[static::class] = true;
349
            static::init();
350
        }
351
    }
352
353
    /**
354
     * 初始化处理
355
     * @access protected
356
     * @return void
357
     */
358
    protected static function init()
359
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
360
361
    protected function checkData(): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function checkData()
Loading history...
362
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
363
364
    protected function checkResult($result): void
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function checkResult()
Loading history...
365
    {}
0 ignored issues
show
Coding Style introduced by
Closing brace must be on a line by itself
Loading history...
366
367
    /**
368
     * 更新是否强制写入数据 而不做比较
369
     * @access public
370
     * @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...
371
     * @return $this
372
     */
373
    public function force(bool $force = true)
374
    {
375
        $this->force = $force;
376
        return $this;
377
    }
378
379
    /**
380
     * 判断force
381
     * @access public
382
     * @return bool
383
     */
384
    public function isForce(): bool
385
    {
386
        return $this->force;
387
    }
388
389
    /**
390
     * 新增数据是否使用Replace
391
     * @access public
392
     * @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...
393
     * @return $this
394
     */
395
    public function replace(bool $replace = true)
396
    {
397
        $this->replace = $replace;
398
        return $this;
399
    }
400
401
    /**
402
     * 刷新模型数据
403
     * @access public
404
     * @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...
405
     * @return $this
406
     */
407
    public function refresh(bool $relation = false)
408
    {
409
        if ($this->exists) {
410
            $this->data   = $this->db()->find($this->getKey())->getData();
411
            $this->origin = $this->data;
412
413
            if ($relation) {
414
                $this->relation = [];
415
            }
416
        }
417
418
        return $this;
419
    }
420
421
    /**
422
     * 设置数据是否存在
423
     * @access public
424
     * @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...
425
     * @return $this
426
     */
427
    public function exists(bool $exists = true)
428
    {
429
        $this->exists = $exists;
430
        return $this;
431
    }
432
433
    /**
434
     * 判断数据是否存在数据库
435
     * @access public
436
     * @return bool
437
     */
438
    public function isExists(): bool
439
    {
440
        return $this->exists;
441
    }
442
443
    /**
444
     * 判断模型是否为空
445
     * @access public
446
     * @return bool
447
     */
448
    public function isEmpty(): bool
449
    {
450
        return empty($this->data);
451
    }
452
453
    /**
454
     * 延迟保存当前数据对象
455
     * @access public
456
     * @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...
457
     * @return void
458
     */
459
    public function lazySave($data = []): void
460
    {
461
        if (false === $data) {
462
            $this->lazySave = false;
463
        } else {
464
            if (is_array($data)) {
465
                $this->setAttrs($data);
466
            }
467
468
            $this->lazySave = true;
469
        }
470
    }
471
472
    /**
473
     * 保存当前数据对象
474
     * @access public
475
     * @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...
476
     * @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...
477
     * @return bool
478
     */
479
    public function save(array $data = [], string $sequence = null): bool
480
    {
481
        // 数据对象赋值
482
        $this->setAttrs($data);
483
484
        if ($this->isEmpty() || false === $this->trigger('BeforeWrite')) {
485
            return false;
486
        }
487
488
        $result = $this->exists ? $this->updateData() : $this->insertData($sequence);
489
490
        if (false === $result) {
491
            return false;
492
        }
493
494
        // 写入回调
495
        $this->trigger('AfterWrite');
496
497
        // 重新记录原始数据
498
        $this->origin   = $this->data;
499
        $this->set      = [];
500
        $this->lazySave = false;
501
502
        return true;
503
    }
504
505
    /**
506
     * 检查数据是否允许写入
507
     * @access protected
508
     * @return array
509
     */
510
    protected function checkAllowFields(): array
511
    {
512
        // 检测字段
513
        if (empty($this->field)) {
514
            if (!empty($this->schema)) {
515
                $this->field = array_keys(array_merge($this->schema, $this->jsonType));
516
            } else {
517
                $query = $this->db();
518
                $table = $this->table ? $this->table . $this->suffix : $query->getTable();
519
520
                $this->field = $query->getConnection()->getTableFields($table);
0 ignored issues
show
Bug introduced by
The method getTableFields() does not exist on think\db\Connection. Since it exists in all sub-types, consider adding an abstract or default implementation to think\db\Connection. ( Ignorable by Annotation )

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

520
                $this->field = $query->getConnection()->/** @scrutinizer ignore-call */ getTableFields($table);
Loading history...
521
            }
522
523
            return $this->field;
524
        }
525
526
        $field = $this->field;
527
528
        if ($this->autoWriteTimestamp) {
529
            array_push($field, $this->createTime, $this->updateTime);
530
        }
531
532
        if (!empty($this->disuse)) {
533
            // 废弃字段
534
            $field = array_diff($field, $this->disuse);
535
        }
536
537
        return $field;
538
    }
539
540
    /**
541
     * 保存写入数据
542
     * @access protected
543
     * @return bool
544
     */
545
    protected function updateData(): bool
546
    {
547
        // 事件回调
548
        if (false === $this->trigger('BeforeUpdate')) {
549
            return false;
550
        }
551
552
        $this->checkData();
553
554
        // 获取有更新的数据
555
        $data = $this->getChangedData();
556
557
        if (empty($data)) {
558
            // 关联更新
559
            if (!empty($this->relationWrite)) {
560
                $this->autoRelationUpdate();
561
            }
562
563
            return true;
564
        }
565
566
        if ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) {
567
            // 自动写入更新时间
568
            $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

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

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

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