1
|
|
|
<?php |
2
|
|
|
// +---------------------------------------------------------------------- |
|
|
|
|
3
|
|
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ] |
4
|
|
|
// +---------------------------------------------------------------------- |
5
|
|
|
// | Copyright (c) 2006~2018 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
|
|
|
|
12
|
|
|
namespace think\model\concern; |
13
|
|
|
|
14
|
|
|
use think\Collection; |
15
|
|
|
use think\Exception; |
16
|
|
|
use think\Loader; |
17
|
|
|
use think\Model; |
18
|
|
|
use think\model\Collection as ModelCollection; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* 模型数据转换处理 |
22
|
|
|
*/ |
|
|
|
|
23
|
|
|
trait Conversion |
24
|
|
|
{ |
25
|
|
|
/** |
26
|
|
|
* 数据输出显示的属性 |
27
|
|
|
* @var array |
28
|
|
|
*/ |
29
|
|
|
protected $visible = []; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* 数据输出隐藏的属性 |
33
|
|
|
* @var array |
34
|
|
|
*/ |
35
|
|
|
protected $hidden = []; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* 数据输出需要追加的属性 |
39
|
|
|
* @var array |
40
|
|
|
*/ |
41
|
|
|
protected $append = []; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* 数据集对象名 |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
protected $resultSetType; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* 设置需要附加的输出属性 |
51
|
|
|
* @access public |
52
|
|
|
* @param array $append 属性列表 |
53
|
|
|
* @param bool $override 是否覆盖 |
54
|
|
|
* @return $this |
55
|
|
|
*/ |
56
|
|
|
public function append(array $append = [], $override = false) |
57
|
|
|
{ |
58
|
|
|
$this->append = $override ? $append : array_merge($this->append, $append); |
59
|
|
|
|
60
|
|
|
return $this; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* 设置附加关联对象的属性 |
65
|
|
|
* @access public |
66
|
|
|
* @param string $attr 关联属性 |
|
|
|
|
67
|
|
|
* @param string|array $append 追加属性名 |
|
|
|
|
68
|
|
|
* @return $this |
69
|
|
|
* @throws Exception |
70
|
|
|
*/ |
71
|
|
|
public function appendRelationAttr($attr, $append) |
72
|
|
|
{ |
73
|
|
|
if (is_string($append)) { |
74
|
|
|
$append = explode(',', $append); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
$relation = Loader::parseName($attr, 1, false); |
78
|
|
|
if (isset($this->relation[$relation])) { |
79
|
|
|
$model = $this->relation[$relation]; |
80
|
|
|
} else { |
81
|
|
|
$model = $this->getRelationData($this->$relation()); |
|
|
|
|
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
if ($model instanceof Model) { |
85
|
|
|
foreach ($append as $key => $attr) { |
|
|
|
|
86
|
|
|
$key = is_numeric($key) ? $attr : $key; |
87
|
|
|
if (isset($this->data[$key])) { |
88
|
|
|
throw new Exception('bind attr has exists:' . $key); |
89
|
|
|
} else { |
90
|
|
|
$this->data[$key] = $model->$attr; |
|
|
|
|
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
return $this; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* 设置需要隐藏的输出属性 |
100
|
|
|
* @access public |
101
|
|
|
* @param array $hidden 属性列表 |
102
|
|
|
* @param bool $override 是否覆盖 |
103
|
|
|
* @return $this |
104
|
|
|
*/ |
105
|
|
|
public function hidden(array $hidden = [], $override = false) |
106
|
|
|
{ |
107
|
|
|
$this->hidden = $override ? $hidden : array_merge($this->hidden, $hidden); |
108
|
|
|
|
109
|
|
|
return $this; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* 设置需要输出的属性 |
114
|
|
|
* @access public |
115
|
|
|
* @param array $visible |
|
|
|
|
116
|
|
|
* @param bool $override 是否覆盖 |
117
|
|
|
* @return $this |
118
|
|
|
*/ |
119
|
|
|
public function visible(array $visible = [], $override = false) |
120
|
|
|
{ |
121
|
|
|
$this->visible = $override ? $visible : array_merge($this->visible, $visible); |
122
|
|
|
|
123
|
|
|
return $this; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* 转换当前模型对象为数组 |
128
|
|
|
* @access public |
129
|
|
|
* @return array |
130
|
|
|
*/ |
131
|
|
|
public function toArray() |
132
|
|
|
{ |
133
|
|
|
$item = []; |
134
|
|
|
$hasVisible = false; |
135
|
|
|
|
136
|
|
|
foreach ($this->visible as $key => $val) { |
137
|
|
|
if (is_string($val)) { |
138
|
|
|
if (strpos($val, '.')) { |
139
|
|
|
list($relation, $name) = explode('.', $val); |
140
|
|
|
$this->visible[$relation][] = $name; |
141
|
|
|
} else { |
142
|
|
|
$this->visible[$val] = true; |
143
|
|
|
$hasVisible = true; |
144
|
|
|
} |
145
|
|
|
unset($this->visible[$key]); |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
foreach ($this->hidden as $key => $val) { |
150
|
|
|
if (is_string($val)) { |
151
|
|
|
if (strpos($val, '.')) { |
152
|
|
|
list($relation, $name) = explode('.', $val); |
153
|
|
|
$this->hidden[$relation][] = $name; |
154
|
|
|
} else { |
155
|
|
|
$this->hidden[$val] = true; |
156
|
|
|
} |
157
|
|
|
unset($this->hidden[$key]); |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
// 合并关联数据 |
162
|
|
|
$data = array_merge($this->data, $this->relation); |
163
|
|
|
|
164
|
|
|
foreach ($data as $key => $val) { |
165
|
|
|
if ($val instanceof Model || $val instanceof ModelCollection) { |
166
|
|
|
// 关联模型对象 |
167
|
|
|
if (isset($this->visible[$key])) { |
168
|
|
|
$val->visible($this->visible[$key]); |
169
|
|
|
} elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) { |
170
|
|
|
$val->hidden($this->hidden[$key]); |
171
|
|
|
} |
172
|
|
|
// 关联模型对象 |
173
|
|
|
if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) { |
174
|
|
|
$item[$key] = $val->toArray(); |
175
|
|
|
} |
176
|
|
|
} elseif (isset($this->visible[$key])) { |
177
|
|
|
$item[$key] = $this->getAttr($key); |
|
|
|
|
178
|
|
|
} elseif (!isset($this->hidden[$key]) && !$hasVisible) { |
179
|
|
|
$item[$key] = $this->getAttr($key); |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
// 追加属性(必须定义获取器) |
184
|
|
|
if (!empty($this->append)) { |
185
|
|
|
foreach ($this->append as $key => $name) { |
186
|
|
|
if (is_array($name)) { |
187
|
|
|
// 追加关联对象属性 |
188
|
|
|
$relation = $this->getRelation($key); |
|
|
|
|
189
|
|
|
|
190
|
|
|
if (!$relation) { |
191
|
|
|
$relation = $this->getAttr($key); |
192
|
|
|
$relation->visible($name); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$item[$key] = $relation->append($name)->toArray(); |
196
|
|
|
} elseif (strpos($name, '.')) { |
197
|
|
|
list($key, $attr) = explode('.', $name); |
198
|
|
|
// 追加关联对象属性 |
199
|
|
|
$relation = $this->getRelation($key); |
200
|
|
|
|
201
|
|
|
if (!$relation) { |
202
|
|
|
$relation = $this->getAttr($key); |
203
|
|
|
$relation->visible([$attr]); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
$item[$key] = $relation->append([$attr])->toArray(); |
207
|
|
|
} else { |
208
|
|
|
$item[$name] = $this->getAttr($name, $item); |
209
|
|
|
} |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
return $item; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* 转换当前模型对象为JSON字符串 |
218
|
|
|
* @access public |
219
|
|
|
* @param integer $options json参数 |
220
|
|
|
* @return string |
221
|
|
|
*/ |
222
|
|
|
public function toJson($options = JSON_UNESCAPED_UNICODE) |
223
|
|
|
{ |
224
|
|
|
return json_encode($this->toArray(), $options); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* 移除当前模型的关联属性 |
229
|
|
|
* @access public |
230
|
|
|
* @return $this |
231
|
|
|
*/ |
232
|
|
|
public function removeRelation() |
233
|
|
|
{ |
234
|
|
|
$this->relation = []; |
|
|
|
|
235
|
|
|
return $this; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
public function __toString() |
|
|
|
|
239
|
|
|
{ |
240
|
|
|
return $this->toJson(); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
// JsonSerializable |
244
|
|
|
public function jsonSerialize() |
|
|
|
|
245
|
|
|
{ |
246
|
|
|
return $this->toArray(); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* 转换数据集为数据集对象 |
251
|
|
|
* @access public |
252
|
|
|
* @param array|Collection $collection 数据集 |
|
|
|
|
253
|
|
|
* @param string $resultSetType 数据集类 |
254
|
|
|
* @return Collection |
255
|
|
|
*/ |
256
|
|
|
public function toCollection($collection, $resultSetType = null) |
257
|
|
|
{ |
258
|
|
|
$resultSetType = $resultSetType ?: $this->resultSetType; |
259
|
|
|
|
260
|
|
|
if ($resultSetType && false !== strpos($resultSetType, '\\')) { |
261
|
|
|
$collection = new $resultSetType($collection); |
262
|
|
|
} else { |
263
|
|
|
$collection = new ModelCollection($collection); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
return $collection; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
} |
270
|
|
|
|