This repository was archived by the owner on May 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 394
Expand file tree
/
Copy pathRObject.php
More file actions
329 lines (298 loc) · 7.26 KB
/
RObject.php
File metadata and controls
329 lines (298 loc) · 7.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
<?php
/**
* 定义Mongo中的对象
*
* 除了setAttr()/setAttrs()/setSource()之外其余的动作都不会直接修改当前对象的属性集,
* 只有调用save()之后才会生效。
*
* 在save()之前多次对同一个方法调用同一个指令,只有最后一个指令才会生效。
* 目前你不能修改对象的ID。
*
*/
class RObject extends RModel implements ArrayAccess {
/**
* Enter description here...
*
* @var MongoCollection
*/
private $_collection;
private $_operations = array();
private $_attrs = array();
private $_id;
/**
* 构造对象
*
* @param array $attrs 属性集
*/
function __construct(array $attrs = array()) {
$this->setAttrs($attrs);
}
/**
* 设置属性值
*
* @param string $name 属性名
* @param mixed $value 属性值
*/
function setAttr($name, $value) {
if ($name == "_id") {
$this->setId($value);
return;
}
$this->_attrs = rock_array_set($this->_attrs, $name, $value);
$this->_execOperator('$set', $name, $value);
}
/**
* 设置属性集
*
* @param array $attrs 属性集
*/
function setAttrs(array $attrs) {
foreach ($attrs as $field => $value) {
$this->setAttr($field, $value);
}
}
/**
* 设置原始属性集,即刚从数据库中查出来的属性集
*
* @param array $attrs 原始属性集
*/
function setSource(array $attrs) {
if (isset($attrs["_id"])) {
$this->setId($attrs["_id"]);
}
$this->_attrs = array_merge($this->_attrs, $attrs);
}
private function _execOperator($operator, $attr, $newValue) {
if (!isset($this->_operations[$operator])) {
$this->_operations[$operator] = array();
}
$this->_operations[$operator][$attr] = $newValue;
}
/**
* 当前对象的ID,可以用来判断对象是否已经存储
*
* @return MongoId
*/
function id() {
return $this->_id;
}
/**
* 取得当前对象的ID值
*
* @return string
*/
function idValue() {
return $this->_id ? $this->_id->__toString() : null;
}
/**
* 设置当前对象的ID
*
* @param string|MongoId $id 新的Id,如果非长度为24的16禁止的字符串,则MongoDB会认为是非法的ID,而忽略之
*/
function setId($id) {
$this->_id = ($id);
}
/**
* 增加一个属性的值
*
* @param string $attr 属性
* @param integer $count 增加的数量
*/
function increase($attr, $count = 1) {
$this->_execOperator('$inc', $attr, $count);
}
/**
* 删除一个属性值。如果是一个集合只会将其值设置为NULL,
* 这时候你需要调用$obj->pull($attrParent, null)来删除null值。
*
* @param string $attr 属性
* @param boolean $pullNull 是否自动删除NULL值
*/
function remove($attr, $pullNull = true) {
if ($pullNull) {
$this->_execOperator('$unset', $attr, 1);
$this->save();
if (strstr($attr, ".")) {
$parent = substr($attr, 0, strrpos($attr, "."));
$this->pull($parent, null);
}
}
else {
$this->_execOperator('$unset', $attr, 1);
}
}
/**
* 在一个集合末尾增加新的元素
*
* 注意索引数组和关联数组不能混合
*
* @param string $attr 属性
* @param mixed $value 属性值
* @param boolean|string|integer $genId 是否自动生成ID,如果是boolean,则可以指定是否自动生成ID,如果是string和integer,则直接使用此值作为ID
*/
function push($attr, $value, $genId = false) {
if (is_bool($genId) && $genId) {
$attr .= "." . strtoupper(uniqid("ID_"));
$this->setAttr($attr, $value);
}
elseif (is_string($genId) || is_integer($genId)) {
$attr .= "." . $genId;
$this->setAttr($attr, $value);
}
else {
$this->_execOperator('$push', $attr, $value);
}
}
/**
* 在一个集合末尾增加一组新的元素
*
* @param string $attr 属性
* @param array $values 属性值
*/
function pushAll($attr, array $values) {
$this->_execOperator('$pushAll', $attr, $values);
}
function addToSet($attr, $value) {
$this->_execOperator('$addToSet', $attr, $value);
}
function addAllToSet($attr, array $values) {
$this->_execOperator('$addToSet', $attr, array( '$each' => $values ));
}
function pop($attr) {
$this->_execOperator('$pop', $attr, 1);
}
function shift($attr) {
$this->_execOperator('$pop', $attr, -1);
}
/**
* 拽出某一个数组中的值为$value的元素
*
* @param string $attr 属性
* @param mixed $value 元素值
*/
function pull($attr, $value) {
$this->_execOperator('$pull', $attr, $value);
}
function pullAll($attr, array $values) {
$this->_execOperator('$pullAll', $attr, $values);
}
/**
* 保存当前对象
*
* @param boolean $refresh 是否刷新当前对象
* @return boolean
*/
function save($refresh = false) {
if (!$this->_collection) {
import("@.RMongoException");
throw new RMongoException("Object is not in any collection, please use setCollection() to method to set a collection.");
}
$bool = true;
if ($this->_id) {//if exists
if (!empty($this->_operations)) {
$bool = $this->_collection->update(array( "_id" => $this->_id ), $this->_operations, array( "upsert" => false, "multiple" => false, "safe" => true ));
if ($refresh) {
$bool = $this->refresh();
}
}
}
else {
$bool = $this->_collection->insert($this->_attrs, true);
if ($bool) {
$this->_id = $this->_attrs["_id"];
import("@.RMongo");
RMongo::setLastInsertId($this->_id->__toString());
}
}
$this->_operations = array();
return $bool;
}
/**
* 刷新当前对象
*
* @return boolean
*/
function refresh() {
if (!$this->_collection) {
import("@.RMongoException");
throw new RMongoException("Object is not in any collection, please use setCollection() to method to set a collection.");
}
if (!$this->_id) {
return true;
}
$this->setSource($this->_collection->findOne( array( "_id" => $this->_id ) ));
return true;
}
function setCollection(MongoCollection $collection) {
$this->_collection = $collection;
}
function attr($name) {
return rock_array_get($this->_attrs, $name);
}
/**
* 取得当前对象的所有属性值
*
* @return array
*/
function attrs() {
return $this->_attrs;
}
/**
* 删除当前对象
*
*/
function delete() {
if ($this->_collection && $this->_id) {
$this->_collection->remove(array( "_id" => $this->_id ));
}
$this->_id = null;
$this->_attrs = array();
}
function __get($name) {
return $this->attr($name);
}
/**
* 判断一个偏移量是否存在
*
* 实现了 ArrayAccess 接口对应方法
*
* @param integer $index
* @return boolean
* @since 1.0
*/
function offsetExists($index) {
return !is_null($this->attr($index));
}
/**
* 从一个偏移量中取得数据
*
* 实现了 ArrayAccess 接口对应方法
*
* @param integer $index 偏移量
* @return mixed
*/
function offsetGet($index) {
return $this->attr($index);
}
/**
* 设置偏移量位置上的值
*
* 实现了 ArrayAccess 接口对应方法
*
* @param integer $index 偏移量
* @param mixed $item 值
*/
function offsetSet($index, $item) {
$this->setAttr($index, $item);
}
/**
* 删除偏移量位置对应的元素
*
* 实现了 ArrayAccess 接口对应方法
*
* @param integer $index 偏移量
*/
function offsetUnset($index) {
$this->setAttr($index, null);
}
}