Completed
Push — 6.0 ( ec25ec...df7e4e )
by liu
03:51
created

RelationShip::getRelation()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 8
ccs 0
cts 5
cp 0
crap 12
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\model\concern;
14
15
use think\App;
16
use think\Collection;
17
use think\db\Query;
18
use think\Exception;
19
use think\Model;
20
use think\model\Relation;
21
use think\model\relation\BelongsTo;
22
use think\model\relation\BelongsToMany;
23
use think\model\relation\HasMany;
24
use think\model\relation\HasManyThrough;
25
use think\model\relation\HasOne;
26
use think\model\relation\MorphMany;
27
use think\model\relation\MorphOne;
28
use think\model\relation\MorphTo;
29
30
/**
31
 * 模型关联处理
32
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package 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...
33
trait RelationShip
34
{
35
    /**
36
     * 父关联模型对象
37
     * @var object
38
     */
39
    private $parent;
0 ignored issues
show
Coding Style introduced by
Private member variable "parent" must be prefixed with an underscore
Loading history...
40
41
    /**
42
     * 模型关联数据
43
     * @var array
44
     */
45
    private $relation = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "relation" must be prefixed with an underscore
Loading history...
46
47
    /**
48
     * 关联写入定义信息
49
     * @var array
50
     */
51
    private $together = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "together" must be prefixed with an underscore
Loading history...
52
53
    /**
54
     * 关联自动写入信息
55
     * @var array
56
     */
57
    protected $relationWrite = [];
58
59
    /**
60
     * 设置父关联对象
61
     * @access public
62
     * @param  Model $model  模型对象
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
63
     * @return $this
64
     */
65
    public function setParent(Model $model)
66
    {
67
        $this->parent = $model;
68
69
        return $this;
70
    }
71
72
    /**
73
     * 获取父关联对象
74
     * @access public
75
     * @return Model
76
     */
77
    public function getParent(): Model
78
    {
79
        return $this->parent;
80
    }
81
82
    /**
83
     * 获取当前模型的关联模型数据
84
     * @access public
85
     * @param  string $name 关联方法名
86
     * @return mixed
87
     */
88
    public function getRelation(string $name = null)
89
    {
90
        if (is_null($name)) {
91
            return $this->relation;
92
        }
93
94
        if (array_key_exists($name, $this->relation)) {
95
            return $this->relation[$name];
96
        }
97
    }
98
99
    /**
100
     * 设置关联数据对象值
101
     * @access public
102
     * @param  string $name  属性名
103
     * @param  mixed  $value 属性值
104
     * @param  array  $data  数据
105
     * @return $this
106
     */
107
    public function setRelation(string $name, $value, array $data = [])
108
    {
109
        // 检测修改器
110
        $method = 'set' . App::parseName($name, 1) . 'Attr';
111
112
        if (method_exists($this, $method)) {
113
            $value = $this->$method($value, array_merge($this->data, $data));
114
        }
115
116
        $this->relation[$name] = $value;
117
118
        return $this;
119
    }
120
121
    /**
122
     * 查询当前模型的关联数据
123
     * @access public
124
     * @param  array $relations 关联名
125
     * @return void
126
     */
127
    public function relationQuery(array $relations): void
128
    {
129
        foreach ($relations as $key => $relation) {
130
            $subRelation = '';
131
            $closure     = null;
132
133
            if ($relation instanceof \Closure) {
134
                // 支持闭包查询过滤关联条件
135
                $closure  = $relation;
136
                $relation = $key;
137
            }
138
139
            if (is_array($relation)) {
140
                $subRelation = $relation;
141
                $relation    = $key;
142
            } elseif (strpos($relation, '.')) {
143
                list($relation, $subRelation) = explode('.', $relation, 2);
144
            }
145
146
            $method = App::parseName($relation, 1, false);
147
148
            $this->relation[$relation] = $this->$method()->getRelation($subRelation, $closure);
149
        }
150
    }
151
152
    /**
153
     * 关联数据写入
154
     * @access public
155
     * @param  array $relation 关联
156
     * @return $this
157
     */
158
    public function together(array $relation)
159
    {
160
        $this->together = $relation;
161
162
        $this->checkAutoRelationWrite();
163
164
        return $this;
165
    }
166
167
    /**
168
     * 根据关联条件查询当前模型
169
     * @access public
170
     * @param  string  $relation 关联方法名
171
     * @param  mixed   $operator 比较操作符
172
     * @param  integer $count    个数
173
     * @param  string  $id       关联表的统计字段
174
     * @param  string  $joinType JOIN类型
175
     * @return Query
176
     */
177
    public static function has(string $relation, string $operator = '>=', int $count = 1, string $id = '*', string $joinType = ''): Query
178
    {
179
        return (new static())
180
            ->$relation()
181
            ->has($operator, $count, $id, $joinType);
182
    }
183
184
    /**
185
     * 根据关联条件查询当前模型
186
     * @access public
187
     * @param  string $relation 关联方法名
188
     * @param  mixed  $where    查询条件(数组或者闭包)
189
     * @param  mixed  $fields   字段
190
     * @param  string $joinType JOIN类型
191
     * @return Query
192
     */
193
    public static function hasWhere(string $relation, $where = [], string $fields = '*', string $joinType = ''): Query
194
    {
195
        return (new static())
196
            ->$relation()
197
            ->hasWhere($where, $fields, $joinType);
198
    }
199
200
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $relations should have a doc-comment as per coding-style.
Loading history...
201
     * 预载入关联查询 返回数据集
202
     * @access public
203
     * @param  array  $resultSet 数据集
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 1 found
Loading history...
204
     * @param  string $relation  关联名
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $relation does not match actual variable name $relations
Loading history...
Coding Style introduced by
Expected 9 spaces after parameter name; 2 found
Loading history...
205
     * @param  array  $withRelationAttr 关联获取器
206
     * @param  bool   $join      是否为JOIN方式
0 ignored issues
show
Coding Style introduced by
Expected 13 spaces after parameter name; 6 found
Loading history...
207
     * @return void
208
     */
209
    public function eagerlyResultSet(array &$resultSet, array $relations, array $withRelationAttr = [], bool $join = false): void
210
    {
211
        foreach ($relations as $key => $relation) {
212
            $subRelation = [];
213
            $closure     = null;
214
215
            if ($relation instanceof \Closure) {
216
                $closure  = $relation;
217
                $relation = $key;
218
            }
219
220
            if (is_array($relation)) {
221
                $subRelation = $relation;
222
                $relation    = $key;
223
            } elseif (strpos($relation, '.')) {
224
                list($relation, $subRelation) = explode('.', $relation, 2);
225
226
                $subRelation = [$subRelation];
227
            }
228
229
            $relation     = App::parseName($relation, 1, false);
230
            $relationName = App::parseName($relation);
231
232
            $relationResult = $this->$relation();
233
234
            if (isset($withRelationAttr[$relationName])) {
235
                $relationResult->withAttr($withRelationAttr[$relationName]);
236
            }
237
238
            $relationResult->eagerlyResultSet($resultSet, $relation, $subRelation, $closure, $join);
239
        }
240
    }
241
242
    /**
243
     * 预载入关联查询 返回模型对象
244
     * @access public
245
     * @param  Model    $result    数据对象
0 ignored issues
show
Coding Style introduced by
Expected 11 spaces after parameter name; 4 found
Loading history...
246
     * @param  array    $relations 关联
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 1 found
Loading history...
247
     * @param  array    $withRelationAttr 关联获取器
248
     * @param  bool     $join      是否为JOIN方式
0 ignored issues
show
Coding Style introduced by
Expected 13 spaces after parameter name; 6 found
Loading history...
249
     * @return void
250
     */
251
    public function eagerlyResult(Model $result, array $relations, array $withRelationAttr = [], bool $join = false): void
252
    {
253
        foreach ($relations as $key => $relation) {
254
            $subRelation = [];
255
            $closure     = null;
256
257
            if ($relation instanceof \Closure) {
258
                $closure  = $relation;
259
                $relation = $key;
260
            }
261
262
            if (is_array($relation)) {
263
                $subRelation = $relation;
264
                $relation    = $key;
265
            } elseif (strpos($relation, '.')) {
266
                list($relation, $subRelation) = explode('.', $relation, 2);
267
268
                $subRelation = [$subRelation];
269
            }
270
271
            $relation     = App::parseName($relation, 1, false);
272
            $relationName = App::parseName($relation);
273
274
            $relationResult = $this->$relation();
275
276
            if (isset($withRelationAttr[$relationName])) {
277
                $relationResult->withAttr($withRelationAttr[$relationName]);
278
            }
279
280
            $relationResult->eagerlyResult($result, $relation, $subRelation, $closure, $join);
281
        }
282
    }
283
284
    /**
285
     * 绑定(一对一)关联属性到当前模型
286
     * @access protected
287
     * @param  string   $relation    关联名称
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
288
     * @param  array    $attrs       绑定属性
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 7 found
Loading history...
289
     * @return $this
290
     * @throws Exception
291
     */
292
    public function bindAttr(string $relation, array $attrs = [])
293
    {
294
        $relation = $this->getRelation($relation);
295
296
        foreach ($attrs as $key => $attr) {
297
            $key   = is_numeric($key) ? $attr : $key;
298
            $value = $this->getOrigin($key);
0 ignored issues
show
Bug introduced by
It seems like getOrigin() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

298
            /** @scrutinizer ignore-call */ 
299
            $value = $this->getOrigin($key);
Loading history...
299
300
            if (!is_null($value)) {
301
                throw new Exception('bind attr has exists:' . $key);
302
            } else {
303
                $this->set($key, $relation ? $relation->$attr : null);
0 ignored issues
show
Bug introduced by
It seems like set() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

303
                $this->/** @scrutinizer ignore-call */ 
304
                       set($key, $relation ? $relation->$attr : null);
Loading history...
304
            }
305
        }
306
307
        return $this;
308
    }
309
310
    /**
311
     * 关联统计
312
     * @access public
313
     * @param  Model    $result     数据对象
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 5 found
Loading history...
314
     * @param  array    $relations  关联名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
315
     * @param  string   $aggregate  聚合查询方法
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
316
     * @param  string   $field      字段
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 6 found
Loading history...
317
     * @return void
318
     */
319
    public function relationCount(Model $result, array $relations, string $aggregate = 'sum', string $field = '*'): void
320
    {
321
        foreach ($relations as $key => $relation) {
322
            $closure = $name = null;
323
324
            if ($relation instanceof \Closure) {
325
                $closure  = $relation;
326
                $relation = $key;
327
            } elseif (is_string($key)) {
328
                $name     = $relation;
329
                $relation = $key;
330
            }
331
332
            $relation = App::parseName($relation, 1, false);
333
            $count    = $this->$relation()->relationCount($result, $closure, $aggregate, $field, $name);
334
335
            if (empty($name)) {
336
                $name = App::parseName($relation) . '_' . $aggregate;
337
            }
338
339
            $result->setAttr($name, $count);
340
        }
341
    }
342
343
    /**
344
     * HAS ONE 关联定义
345
     * @access public
346
     * @param  string $model      模型名
347
     * @param  string $foreignKey 关联外键
348
     * @param  string $localKey   当前主键
349
     * @return HasOne
350
     */
351
    public function hasOne(string $model, string $foreignKey = '', string $localKey = ''): HasOne
352
    {
353
        // 记录当前关联信息
354
        $model      = $this->parseModel($model);
355
        $localKey   = $localKey ?: $this->getPk();
0 ignored issues
show
Bug introduced by
It seems like getPk() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

355
        $localKey   = $localKey ?: $this->/** @scrutinizer ignore-call */ getPk();
Loading history...
356
        $foreignKey = $foreignKey ?: $this->getForeignKey($this->name);
357
358
        return new HasOne($this, $model, $foreignKey, $localKey);
359
    }
360
361
    /**
362
     * BELONGS TO 关联定义
363
     * @access public
364
     * @param  string $model      模型名
365
     * @param  string $foreignKey 关联外键
366
     * @param  string $localKey   关联主键
367
     * @return BelongsTo
368
     */
369
    public function belongsTo(string $model, string $foreignKey = '', string $localKey = ''): BelongsTo
370
    {
371
        // 记录当前关联信息
372
        $model      = $this->parseModel($model);
373
        $foreignKey = $foreignKey ?: $this->getForeignKey((new $model)->getName());
374
        $localKey   = $localKey ?: (new $model)->getPk();
375
        $trace      = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
376
        $relation   = App::parseName($trace[1]['function']);
377
378
        return new BelongsTo($this, $model, $foreignKey, $localKey, $relation);
379
    }
380
381
    /**
382
     * HAS MANY 关联定义
383
     * @access public
384
     * @param  string $model      模型名
385
     * @param  string $foreignKey 关联外键
386
     * @param  string $localKey   当前主键
387
     * @return HasMany
388
     */
389
    public function hasMany(string $model, string $foreignKey = '', string $localKey = ''): HasMany
390
    {
391
        // 记录当前关联信息
392
        $model      = $this->parseModel($model);
393
        $localKey   = $localKey ?: $this->getPk();
394
        $foreignKey = $foreignKey ?: $this->getForeignKey($this->name);
395
396
        return new HasMany($this, $model, $foreignKey, $localKey);
397
    }
398
399
    /**
400
     * HAS MANY 远程关联定义
401
     * @access public
402
     * @param  string $model      模型名
403
     * @param  string $through    中间模型名
404
     * @param  string $foreignKey 关联外键
405
     * @param  string $throughKey 关联外键
406
     * @param  string $localKey   当前主键
407
     * @return HasManyThrough
408
     */
409
    public function hasManyThrough(string $model, string $through, string $foreignKey = '', string $throughKey = '', string $localKey = ''): HasManyThrough
410
    {
411
        // 记录当前关联信息
412
        $model      = $this->parseModel($model);
413
        $through    = $this->parseModel($through);
414
        $localKey   = $localKey ?: $this->getPk();
415
        $foreignKey = $foreignKey ?: $this->getForeignKey($this->name);
416
        $throughKey = $throughKey ?: $this->getForeignKey((new $through)->getName());
417
418
        return new HasManyThrough($this, $model, $through, $foreignKey, $throughKey, $localKey);
419
    }
420
421
    /**
422
     * BELONGS TO MANY 关联定义
423
     * @access public
424
     * @param  string $model      模型名
425
     * @param  string $table      中间表名
426
     * @param  string $foreignKey 关联外键
427
     * @param  string $localKey   当前模型关联键
428
     * @return BelongsToMany
429
     */
430
    public function belongsToMany(string $model, string $table = '', string $foreignKey = '', string $localKey = ''): BelongsToMany
431
    {
432
        // 记录当前关联信息
433
        $model      = $this->parseModel($model);
434
        $name       = App::parseName(App::classBaseName($model));
435
        $table      = $table ?: App::parseName($this->name) . '_' . $name;
436
        $foreignKey = $foreignKey ?: $name . '_id';
437
        $localKey   = $localKey ?: $this->getForeignKey($this->name);
438
439
        return new BelongsToMany($this, $model, $table, $foreignKey, $localKey);
440
    }
441
442
    /**
443
     * MORPH  One 关联定义
444
     * @access public
445
     * @param  string       $model 模型名
446
     * @param  string|array $morph 多态字段信息
447
     * @param  string       $type  多态类型
448
     * @return MorphOne
449
     */
450
    public function morphOne(string $model, $morph = null, string $type = ''): MorphOne
451
    {
452
        // 记录当前关联信息
453
        $model = $this->parseModel($model);
454
455
        if (is_null($morph)) {
456
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
457
            $morph = App::parseName($trace[1]['function']);
458
        }
459
460
        if (is_array($morph)) {
461
            list($morphType, $foreignKey) = $morph;
462
        } else {
463
            $morphType  = $morph . '_type';
464
            $foreignKey = $morph . '_id';
465
        }
466
467
        $type = $type ?: get_class($this);
468
469
        return new MorphOne($this, $model, $foreignKey, $morphType, $type);
470
    }
471
472
    /**
473
     * MORPH  MANY 关联定义
474
     * @access public
475
     * @param  string       $model 模型名
476
     * @param  string|array $morph 多态字段信息
477
     * @param  string       $type  多态类型
478
     * @return MorphMany
479
     */
480
    public function morphMany(string $model, $morph = null, string $type = ''): MorphMany
481
    {
482
        // 记录当前关联信息
483
        $model = $this->parseModel($model);
484
485
        if (is_null($morph)) {
486
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
487
            $morph = App::parseName($trace[1]['function']);
488
        }
489
490
        $type = $type ?: get_class($this);
491
492
        if (is_array($morph)) {
493
            list($morphType, $foreignKey) = $morph;
494
        } else {
495
            $morphType  = $morph . '_type';
496
            $foreignKey = $morph . '_id';
497
        }
498
499
        return new MorphMany($this, $model, $foreignKey, $morphType, $type);
500
    }
501
502
    /**
503
     * MORPH TO 关联定义
504
     * @access public
505
     * @param  string|array $morph 多态字段信息
506
     * @param  array        $alias 多态别名定义
507
     * @return MorphTo
508
     */
509
    public function morphTo($morph = null, array $alias = []): MorphTo
510
    {
511
        $trace    = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
512
        $relation = App::parseName($trace[1]['function']);
513
514
        if (is_null($morph)) {
515
            $morph = $relation;
516
        }
517
518
        // 记录当前关联信息
519
        if (is_array($morph)) {
520
            list($morphType, $foreignKey) = $morph;
521
        } else {
522
            $morphType  = $morph . '_type';
523
            $foreignKey = $morph . '_id';
524
        }
525
526
        return new MorphTo($this, $morphType, $foreignKey, $alias, $relation);
527
    }
528
529
    /**
530
     * 解析模型的完整命名空间
531
     * @access protected
532
     * @param  string $model 模型名(或者完整类名)
533
     * @return string
534
     */
535
    protected function parseModel(string $model): string
536
    {
537
        if (false === strpos($model, '\\')) {
538
            $path = explode('\\', static::class);
539
            array_pop($path);
540
            array_push($path, App::parseName($model, 1));
541
            $model = implode('\\', $path);
542
        }
543
544
        return $model;
545
    }
546
547
    /**
548
     * 获取模型的默认外键名
549
     * @access protected
550
     * @param  string $name 模型名
551
     * @return string
552
     */
553
    protected function getForeignKey(string $name): string
554
    {
555
        if (strpos($name, '\\')) {
556
            $name = App::classBaseName($name);
557
        }
558
559
        return App::parseName($name) . '_id';
560
    }
561
562
    /**
563
     * 检查属性是否为关联属性 如果是则返回关联方法名
564
     * @access protected
565
     * @param  string $attr 关联属性名
566
     * @return string|false
567
     */
568
    protected function isRelationAttr(string $attr)
569
    {
570
        $relation = App::parseName($attr, 1, false);
571
572
        if (method_exists($this, $relation) && !method_exists('think\Model', $relation)) {
573
            return $relation;
574
        }
575
576
        return false;
577
    }
578
579
    /**
580
     * 智能获取关联模型数据
581
     * @access protected
582
     * @param  Relation  $modelRelation 模型关联对象
583
     * @return mixed
584
     */
585
    protected function getRelationData(Relation $modelRelation)
586
    {
587
        if ($this->parent && !$modelRelation->isSelfRelation() && get_class($this->parent) == get_class($modelRelation->getModel())) {
588
            return $this->parent;
589
        }
590
591
        // 获取关联数据
592
        return $modelRelation->getModel()->getRelation();
593
    }
594
595
    /**
596
     * 关联数据自动写入检查
597
     * @access protected
598
     * @return void
599
     */
600
    protected function checkAutoRelationWrite(): void
601
    {
602
        foreach ($this->together as $key => $name) {
603
            if (is_array($name)) {
604
                if (key($name) === 0) {
605
                    $this->relationWrite[$key] = [];
606
                    // 绑定关联属性
607
                    foreach ($name as $val) {
608
                        if (isset($this->data[$val])) {
609
                            $this->relationWrite[$key][$val] = $this->data[$val];
610
                        }
611
                    }
612
                } else {
613
                    // 直接传入关联数据
614
                    $this->relationWrite[$key] = $name;
615
                }
616
            } elseif (isset($this->relation[$name])) {
617
                $this->relationWrite[$name] = $this->relation[$name];
618
            } elseif (isset($this->data[$name])) {
619
                $this->relationWrite[$name] = $this->data[$name];
620
                unset($this->data[$name]);
621
            }
622
        }
623
    }
624
625
    /**
626
     * 自动关联数据更新(针对一对一关联)
627
     * @access protected
628
     * @return void
629
     */
630
    protected function autoRelationUpdate(): void
631
    {
632
        foreach ($this->relationWrite as $name => $val) {
633
            if ($val instanceof Model) {
634
                $val->exists(true)->save();
635
            } else {
636
                $model = $this->getRelation($name);
637
638
                if ($model instanceof Model) {
639
                    $model->exists(true)->save($val);
640
                }
641
            }
642
        }
643
    }
644
645
    /**
646
     * 自动关联数据写入(针对一对一关联)
647
     * @access protected
648
     * @return void
649
     */
650
    protected function autoRelationInsert(): void
651
    {
652
        foreach ($this->relationWrite as $name => $val) {
653
            $method = App::parseName($name, 1, false);
654
            $this->$method()->save($val);
655
        }
656
    }
657
658
    /**
659
     * 自动关联数据删除(支持一对一及一对多关联)
660
     * @access protected
661
     * @return void
662
     */
663
    protected function autoRelationDelete(): void
664
    {
665
        foreach ($this->relationWrite as $key => $name) {
666
            $name   = is_numeric($key) ? $name : $key;
667
            $result = $this->getRelation($name);
668
669
            if ($result instanceof Model) {
670
                $result->delete();
671
            } elseif ($result instanceof Collection) {
672
                foreach ($result as $model) {
673
                    $model->delete();
674
                }
675
            }
676
        }
677
    }
678
679
    /**
680
     * 移除当前模型的关联属性
681
     * @access public
682
     * @return $this
683
     */
684
    public function removeRelation()
685
    {
686
        $this->relation = [];
687
        return $this;
688
    }
689
}
690