Passed
Push — 6.0 ( 479aa7...dc94b0 )
by liu
02:59
created

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

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

615
            $data[$this->updateTime]       = $this->autoWriteTimestamp(/** @scrutinizer ignore-type */ $this->updateTime);
Loading history...
616
            $this->data[$this->updateTime] = $data[$this->updateTime];
617
        }
618
619
        // 检查允许字段
620
        $allowFields = $this->checkAllowFields($auto);
621
622
        foreach ($this->relationWrite as $name => $val) {
623
            if (!is_array($val)) {
624
                continue;
625
            }
626
627
            foreach ($val as $key) {
628
                if (isset($data[$key])) {
629
                    unset($data[$key]);
630
                }
631
            }
632
        }
633
634
        // 模型更新
635
        $db = $this->db();
636
        $db->startTrans();
637
638
        try {
639
            $where  = $this->getWhere();
640
            $result = $db->where($where)
641
                ->strict(false)
642
                ->field($allowFields)
643
                ->update($data);
644
645
            $this->checkResult($result);
646
647
            // 关联更新
648
            if (!empty($this->relationWrite)) {
649
                $this->autoRelationUpdate();
650
            }
651
652
            $db->commit();
653
654
            // 更新回调
655
            $this->trigger('AfterUpdate');
656
657
            return true;
658
        } catch (\Exception $e) {
659
            $db->rollback();
660
            throw $e;
661
        }
662
    }
663
664
    /**
665
     * 新增写入数据
666
     * @access protected
667
     * @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...
668
     * @return bool
669
     */
670
    protected function insertData(string $sequence = null): bool
671
    {
672
        // 自动写入
673
        $auto = array_merge($this->auto, $this->insert);
674
675
        $this->autoCompleteData($auto);
676
677
        // 时间戳自动写入
678
        if ($this->autoWriteTimestamp) {
679
            if ($this->createTime && !isset($this->data[$this->createTime])) {
680
                $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

680
                $this->data[$this->createTime] = $this->autoWriteTimestamp(/** @scrutinizer ignore-type */ $this->createTime);
Loading history...
681
            }
682
683
            if ($this->updateTime && !isset($this->data[$this->updateTime])) {
684
                $this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
685
            }
686
        }
687
688
        if (false === $this->trigger('BeforeInsert')) {
689
            return false;
690
        }
691
692
        $this->checkData();
693
694
        // 检查允许字段
695
        $allowFields = $this->checkAllowFields($auto);
696
697
        $db = $this->db();
698
        $db->startTrans();
699
700
        try {
701
            $result = $db->strict(false)
702
                ->field($allowFields)
703
                ->replace($this->replace)
704
                ->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

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