|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace voku\db; |
|
4
|
|
|
|
|
5
|
|
|
use Arrayy\Arrayy; |
|
6
|
|
|
use voku\db\exceptions\ActiveRecordException; |
|
7
|
|
|
use voku\db\exceptions\FetchingException; |
|
8
|
|
|
|
|
9
|
|
|
/** |
|
10
|
|
|
* A simple implement of active record via Arrayy. |
|
11
|
|
|
* |
|
12
|
|
|
* @method $this select(string $dbProperty) |
|
13
|
|
|
* @method $this eq(string $dbProperty, string | null $value = null) |
|
14
|
|
|
* @method $this from(string $table) |
|
15
|
|
|
* @method $this where(string $where) |
|
16
|
|
|
* @method $this having(string $having) |
|
17
|
|
|
* @method $this limit(int $start, int | null $end = null) |
|
18
|
|
|
* |
|
19
|
|
|
* @method $this equal(string $dbProperty, string $value) |
|
20
|
|
|
* @method $this notEqual(string $dbProperty, string $value) |
|
21
|
|
|
* @method $this ne(string $dbProperty, string $value) |
|
22
|
|
|
* @method $this greaterThan(string $dbProperty, int $value) |
|
23
|
|
|
* @method $this gt(string $dbProperty, int $value) |
|
24
|
|
|
* @method $this lessThan(string $dbProperty, int $value) |
|
25
|
|
|
* @method $this lt(string $dbProperty, int $value) |
|
26
|
|
|
* @method $this greaterThanOrEqual(string $dbProperty, int $value) |
|
27
|
|
|
* @method $this ge(string $dbProperty, int $value) |
|
28
|
|
|
* @method $this gte(string $dbProperty, int $value) |
|
29
|
|
|
* @method $this lessThanOrEqual(string $dbProperty, int $value) |
|
30
|
|
|
* @method $this le(string $dbProperty, int $value) |
|
31
|
|
|
* @method $this lte(string $dbProperty, int $value) |
|
32
|
|
|
* @method $this between(string $dbProperty, array $value) |
|
33
|
|
|
* @method $this like(string $dbProperty, string $value) |
|
34
|
|
|
* @method $this in(string $dbProperty, array $value) |
|
35
|
|
|
* @method $this notIn(string $dbProperty, array $value) |
|
36
|
|
|
* @method $this isnull(string $dbProperty) |
|
37
|
|
|
* @method $this isNotNull(string $dbProperty) |
|
38
|
|
|
* @method $this notNull(string $dbProperty) |
|
39
|
|
|
*/ |
|
40
|
|
|
abstract class ActiveRecord extends Arrayy |
|
41
|
|
|
{ |
|
42
|
|
|
/** |
|
43
|
|
|
* @var DB static property to connect database. |
|
44
|
|
|
*/ |
|
45
|
|
|
protected static $db; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* @var array maping the function name and the operator, to build Expressions in WHERE condition. |
|
49
|
|
|
* |
|
50
|
|
|
* user can call it like this: |
|
51
|
|
|
* <pre> |
|
52
|
|
|
* $user->isnotnull()->eq('id', 1); |
|
53
|
|
|
* </pre> |
|
54
|
|
|
* |
|
55
|
|
|
* will create Expressions can explain to SQL: |
|
56
|
|
|
* <pre> |
|
57
|
|
|
* WHERE user.id IS NOT NULL AND user.id = :ph1 |
|
58
|
|
|
* </pre> |
|
59
|
|
|
*/ |
|
60
|
|
|
protected static $operators = array( |
|
61
|
|
|
'equal' => '=', |
|
62
|
|
|
'eq' => '=', |
|
63
|
|
|
'notequal' => '<>', |
|
64
|
|
|
'ne' => '<>', |
|
65
|
|
|
'greaterthan' => '>', |
|
66
|
|
|
'gt' => '>', |
|
67
|
|
|
'lessthan' => '<', |
|
68
|
|
|
'lt' => '<', |
|
69
|
|
|
'greaterthanorequal' => '>=', |
|
70
|
|
|
'ge' => '>=', |
|
71
|
|
|
'gte' => '>=', |
|
72
|
|
|
'lessthanorequal' => '<=', |
|
73
|
|
|
'le' => '<=', |
|
74
|
|
|
'lte' => '<=', |
|
75
|
|
|
'between' => 'BETWEEN', |
|
76
|
|
|
'like' => 'LIKE', |
|
77
|
|
|
'in' => 'IN', |
|
78
|
|
|
'notin' => 'NOT IN', |
|
79
|
|
|
'isnull' => 'IS NULL', |
|
80
|
|
|
'isnotnull' => 'IS NOT NULL', |
|
81
|
|
|
'notnull' => 'IS NOT NULL', |
|
82
|
|
|
); |
|
83
|
|
|
|
|
84
|
|
|
/** |
|
85
|
|
|
* @var array Part of SQL, maping the function name and the operator to build SQL Part. |
|
86
|
|
|
* <pre>call function like this: |
|
87
|
|
|
* $user->order('id DESC', 'name ASC')->limit(2, 1); |
|
88
|
|
|
* can explain to SQL: |
|
89
|
|
|
* ORDER BY id DESC, name ASC LIMIT 2,1</pre> |
|
90
|
|
|
*/ |
|
91
|
|
|
protected $sqlParts = array( |
|
92
|
|
|
'select' => 'SELECT', |
|
93
|
|
|
'from' => 'FROM', |
|
94
|
|
|
'set' => 'SET', |
|
95
|
|
|
'where' => 'WHERE', |
|
96
|
|
|
'group' => 'GROUP BY', |
|
97
|
|
|
'having' => 'HAVING', |
|
98
|
|
|
'order' => 'ORDER BY', |
|
99
|
|
|
'limit' => 'LIMIT', |
|
100
|
|
|
'top' => 'TOP', |
|
101
|
|
|
); |
|
102
|
|
|
|
|
103
|
|
|
/** |
|
104
|
|
|
* @var array Static property to stored the default Sql Expressions values. |
|
105
|
|
|
*/ |
|
106
|
|
|
protected $defaultSqlExpressions = array( |
|
107
|
|
|
'expressions' => array(), |
|
108
|
|
|
'wrap' => false, |
|
109
|
|
|
'select' => null, |
|
110
|
|
|
'insert' => null, |
|
111
|
|
|
'update' => null, |
|
112
|
|
|
'set' => null, |
|
113
|
|
|
'delete' => 'DELETE ', |
|
114
|
|
|
'join' => null, |
|
115
|
|
|
'from' => null, |
|
116
|
|
|
'values' => null, |
|
117
|
|
|
'where' => null, |
|
118
|
|
|
'having' => null, |
|
119
|
|
|
'limit' => null, |
|
120
|
|
|
'order' => null, |
|
121
|
|
|
'group' => null, |
|
122
|
|
|
); |
|
123
|
|
|
|
|
124
|
|
|
/** |
|
125
|
|
|
* @var array Stored the Expressions of the SQL. |
|
126
|
|
|
*/ |
|
127
|
|
|
protected $sqlExpressions = array(); |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* @var string The table name in database. |
|
131
|
|
|
*/ |
|
132
|
|
|
protected $table; |
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* @var string The primary key of this ActiveRecord, just suport single primary key. |
|
136
|
|
|
*/ |
|
137
|
|
|
protected $primaryKeyName = 'id'; |
|
138
|
|
|
|
|
139
|
|
|
/** |
|
140
|
|
|
* @var array Stored the drity data of this object, when call "insert" or "update" function, will write this data |
|
141
|
|
|
* into database. |
|
142
|
|
|
*/ |
|
143
|
|
|
protected $dirty = array(); |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* @var bool |
|
147
|
|
|
*/ |
|
148
|
|
|
protected static $new_data_are_dirty = true; |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* @var array Stored the params will bind to SQL when call DB->query(), |
|
152
|
|
|
*/ |
|
153
|
|
|
protected $params = array(); |
|
154
|
|
|
|
|
155
|
|
|
/** |
|
156
|
|
|
* @var ActiveRecordExpressions[] Stored the configure of the relation, or target of the relation. |
|
157
|
|
|
*/ |
|
158
|
|
|
protected $relations = array(); |
|
159
|
|
|
|
|
160
|
|
|
/** |
|
161
|
|
|
* @var int The count of bind params, using this count and const "PREFIX" (:ph) to generate place holder in SQL. |
|
162
|
|
|
*/ |
|
163
|
|
|
private static $count = 0; |
|
164
|
|
|
|
|
165
|
|
|
const BELONGS_TO = 'belongs_to'; |
|
166
|
|
|
const HAS_MANY = 'has_many'; |
|
167
|
|
|
const HAS_ONE = 'has_one'; |
|
168
|
|
|
|
|
169
|
|
|
const PREFIX = ':active_record'; |
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* @return array |
|
173
|
|
|
*/ |
|
174
|
|
|
public function getParams() |
|
175
|
|
|
{ |
|
176
|
|
|
return $this->params; |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* @return string |
|
181
|
|
|
*/ |
|
182
|
|
|
public function getPrimaryKeyName() |
|
183
|
|
|
{ |
|
184
|
|
|
return $this->primaryKeyName; |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* @return mixed|null |
|
189
|
|
|
*/ |
|
190
|
12 |
|
public function getPrimaryKey() |
|
191
|
|
|
{ |
|
192
|
12 |
|
$id = $this->{$this->primaryKeyName}; |
|
193
|
12 |
|
if ($id) { |
|
194
|
11 |
|
return $id; |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
1 |
|
return null; |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
|
|
/** |
|
201
|
|
|
* @param mixed $primaryKey |
|
202
|
|
|
* @param bool $dirty |
|
203
|
|
|
* |
|
204
|
|
|
* @return $this |
|
205
|
|
|
*/ |
|
206
|
1 |
|
public function setPrimaryKey($primaryKey, $dirty = true) |
|
207
|
|
|
{ |
|
208
|
1 |
|
if ($dirty === true) { |
|
209
|
1 |
|
$this->dirty[$this->primaryKeyName] = $primaryKey; |
|
210
|
1 |
|
} else { |
|
211
|
|
|
$this->array[$this->primaryKeyName] = $primaryKey; |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
1 |
|
return $this; |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
/** |
|
218
|
|
|
* @return string |
|
219
|
|
|
*/ |
|
220
|
|
|
public function getTable() |
|
221
|
|
|
{ |
|
222
|
|
|
return $this->table; |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
/** |
|
226
|
|
|
* Function to reset the $params and $sqlExpressions. |
|
227
|
|
|
* |
|
228
|
|
|
* @return $this |
|
229
|
|
|
*/ |
|
230
|
22 |
|
public function reset() |
|
231
|
|
|
{ |
|
232
|
22 |
|
$this->params = array(); |
|
233
|
22 |
|
$this->sqlExpressions = array(); |
|
234
|
|
|
|
|
235
|
22 |
|
return $this; |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
/** |
|
239
|
|
|
* Reset the dirty data. |
|
240
|
|
|
* |
|
241
|
|
|
* @return $this |
|
242
|
|
|
*/ |
|
243
|
5 |
|
public function resetDirty() |
|
244
|
|
|
{ |
|
245
|
5 |
|
$this->dirty = array(); |
|
246
|
|
|
|
|
247
|
5 |
|
return $this; |
|
248
|
|
|
} |
|
249
|
|
|
|
|
250
|
|
|
/** |
|
251
|
|
|
* set the DB connection. |
|
252
|
|
|
* |
|
253
|
|
|
* @param DB $db |
|
254
|
|
|
*/ |
|
255
|
|
|
public static function setDb($db) |
|
256
|
|
|
{ |
|
257
|
|
|
self::$db = $db; |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
/** |
|
261
|
|
|
* Function to find one record and assign in to current object. |
|
262
|
|
|
* |
|
263
|
|
|
* @param mixed $id <p> |
|
264
|
|
|
* If call this function using this param, we will find the record by using this id. |
|
265
|
|
|
* If not set, just find the first record in database. |
|
266
|
|
|
* </p> |
|
267
|
|
|
* |
|
268
|
|
|
* @return false|$this <p> |
|
269
|
|
|
* If we could find the record, assign in to current object and return it, |
|
270
|
|
|
* otherwise return "false". |
|
271
|
|
|
* </p> |
|
272
|
|
|
*/ |
|
273
|
11 |
View Code Duplication |
public function fetch($id = null) |
|
|
|
|
|
|
274
|
|
|
{ |
|
275
|
11 |
|
if ($id) { |
|
276
|
6 |
|
$this->reset()->eq($this->primaryKeyName, $id); |
|
277
|
6 |
|
} |
|
278
|
|
|
|
|
279
|
11 |
|
return self::query( |
|
280
|
11 |
|
$this->limit(1)->_buildSql( |
|
|
|
|
|
|
281
|
|
|
array( |
|
282
|
11 |
|
'select', |
|
283
|
11 |
|
'from', |
|
284
|
11 |
|
'join', |
|
285
|
11 |
|
'where', |
|
286
|
11 |
|
'group', |
|
287
|
11 |
|
'having', |
|
288
|
11 |
|
'order', |
|
289
|
11 |
|
'limit', |
|
290
|
|
|
) |
|
291
|
11 |
|
), |
|
292
|
11 |
|
$this->params, |
|
293
|
11 |
|
$this->reset(), |
|
294
|
|
|
true |
|
295
|
11 |
|
); |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
/** |
|
299
|
|
|
* @param string $query |
|
300
|
|
|
* |
|
301
|
|
|
* @return $this[] |
|
302
|
|
|
*/ |
|
303
|
1 |
|
public function fetchManyByQuery($query) |
|
304
|
|
|
{ |
|
305
|
1 |
|
$list = $this->fetchByQuery($query); |
|
306
|
|
|
|
|
307
|
1 |
|
if (!$list || empty($list)) { |
|
308
|
|
|
return array(); |
|
309
|
|
|
} |
|
310
|
|
|
|
|
311
|
1 |
|
return $list; |
|
312
|
|
|
} |
|
313
|
|
|
|
|
314
|
|
|
/** |
|
315
|
|
|
* @param string $query |
|
316
|
|
|
* |
|
317
|
|
|
* @return $this|null |
|
318
|
|
|
*/ |
|
319
|
1 |
|
public function fetchOneByQuery($query) |
|
320
|
|
|
{ |
|
321
|
1 |
|
$list = $this->fetchByQuery($query); |
|
322
|
|
|
|
|
323
|
1 |
|
if (!$list || empty($list)) { |
|
324
|
|
|
return null; |
|
325
|
|
|
} |
|
326
|
|
|
|
|
327
|
1 |
|
if (is_array($list) && count($list) > 0) { |
|
328
|
1 |
|
$this->array = $list[0]->getArray(); |
|
329
|
1 |
|
} else { |
|
330
|
|
|
$this->array = $list->getArray(); |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
1 |
|
return $this; |
|
334
|
|
|
} |
|
335
|
|
|
|
|
336
|
|
|
/** |
|
337
|
|
|
* @param mixed $id |
|
338
|
|
|
* |
|
339
|
|
|
* @return $this |
|
340
|
|
|
* |
|
341
|
|
|
* @throws FetchingException <p>Will be thrown, if we can not find the id.</p> |
|
342
|
|
|
*/ |
|
343
|
2 |
|
public function fetchById($id) |
|
344
|
|
|
{ |
|
345
|
2 |
|
$obj = $this->fetchByIdIfExists($id); |
|
346
|
2 |
|
if ($obj === null) { |
|
347
|
1 |
|
throw new FetchingException("No row with primary key '$id' in table '$this->table'."); |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
1 |
|
return $obj; |
|
|
|
|
|
|
351
|
|
|
} |
|
352
|
|
|
|
|
353
|
|
|
/** |
|
354
|
|
|
* @param mixed $id |
|
355
|
|
|
* |
|
356
|
|
|
* @return $this|null |
|
357
|
|
|
*/ |
|
358
|
4 |
|
public function fetchByIdIfExists($id) |
|
359
|
|
|
{ |
|
360
|
4 |
|
$list = $this->fetch($id); |
|
361
|
|
|
|
|
362
|
4 |
|
if (!$list || $list->isEmpty()) { |
|
363
|
2 |
|
return null; |
|
364
|
|
|
} |
|
365
|
|
|
|
|
366
|
2 |
|
return $list; |
|
367
|
|
|
} |
|
368
|
|
|
|
|
369
|
|
|
/** |
|
370
|
|
|
* @param array $ids |
|
371
|
|
|
* |
|
372
|
|
|
* @return $this[] |
|
373
|
|
|
*/ |
|
374
|
2 |
|
public function fetchByIds($ids) |
|
375
|
|
|
{ |
|
376
|
2 |
|
if (empty($ids)) { |
|
377
|
|
|
return array(); |
|
378
|
|
|
} |
|
379
|
|
|
|
|
380
|
2 |
|
$list = $this->fetchAll($ids); |
|
381
|
2 |
|
if (is_array($list) && count($list) > 0) { |
|
382
|
1 |
|
return $list; |
|
383
|
|
|
} |
|
384
|
|
|
|
|
385
|
1 |
|
return array(); |
|
386
|
|
|
} |
|
387
|
|
|
|
|
388
|
|
|
/** |
|
389
|
|
|
* @param string $query |
|
390
|
|
|
* |
|
391
|
|
|
* @return $this[]|$this |
|
392
|
|
|
*/ |
|
393
|
2 |
|
public function fetchByQuery($query) |
|
394
|
|
|
{ |
|
395
|
2 |
|
$list = self::query( |
|
396
|
2 |
|
$query, |
|
397
|
2 |
|
$this->params, |
|
398
|
2 |
|
$this->reset() |
|
399
|
2 |
|
); |
|
400
|
|
|
|
|
401
|
2 |
|
if (is_array($list)) { |
|
402
|
2 |
|
if (count($list) === 0) { |
|
403
|
|
|
return array(); |
|
404
|
|
|
} |
|
405
|
|
|
|
|
406
|
2 |
|
return $list; |
|
407
|
|
|
} |
|
408
|
|
|
|
|
409
|
|
|
$this->array = $list->getArray(); |
|
410
|
|
|
|
|
411
|
|
|
return $this; |
|
412
|
|
|
} |
|
413
|
|
|
|
|
414
|
|
|
/** |
|
415
|
|
|
* @param array $ids |
|
416
|
|
|
* |
|
417
|
|
|
* @return $this[] |
|
418
|
|
|
*/ |
|
419
|
1 |
|
public function fetchByIdsPrimaryKeyAsArrayIndex($ids) |
|
420
|
|
|
{ |
|
421
|
1 |
|
$result = $this->fetchAll($ids); |
|
422
|
|
|
|
|
423
|
1 |
|
$resultNew = array(); |
|
424
|
1 |
|
foreach ($result as $item) { |
|
|
|
|
|
|
425
|
1 |
|
$resultNew[$item->getPrimaryKey()] = $item; |
|
426
|
1 |
|
} |
|
427
|
|
|
|
|
428
|
1 |
|
return $resultNew; |
|
429
|
|
|
} |
|
430
|
|
|
|
|
431
|
|
|
/** |
|
432
|
|
|
* Function to find all records in database. |
|
433
|
|
|
* |
|
434
|
|
|
* @param array|null $ids <p> |
|
435
|
|
|
* If call this function using this param, we will find the record by using this id's. |
|
436
|
|
|
* If not set, just find all records in database. |
|
437
|
|
|
* </p> |
|
438
|
|
|
* |
|
439
|
|
|
* @return $this[] |
|
440
|
|
|
*/ |
|
441
|
6 |
View Code Duplication |
public function fetchAll(array $ids = null) |
|
|
|
|
|
|
442
|
|
|
{ |
|
443
|
6 |
|
if ($ids) { |
|
444
|
3 |
|
$this->reset()->in($this->primaryKeyName, $ids); |
|
445
|
3 |
|
} |
|
446
|
|
|
|
|
447
|
6 |
|
return self::query( |
|
448
|
6 |
|
$this->_buildSql( |
|
449
|
|
|
array( |
|
450
|
6 |
|
'select', |
|
451
|
6 |
|
'from', |
|
452
|
6 |
|
'join', |
|
453
|
6 |
|
'where', |
|
454
|
6 |
|
'group', |
|
455
|
6 |
|
'having', |
|
456
|
6 |
|
'order', |
|
457
|
6 |
|
'limit', |
|
458
|
|
|
) |
|
459
|
6 |
|
), |
|
460
|
6 |
|
$this->params, |
|
461
|
6 |
|
$this->reset() |
|
462
|
6 |
|
); |
|
463
|
|
|
} |
|
464
|
|
|
|
|
465
|
|
|
/** |
|
466
|
|
|
* Function to delete current record in database. |
|
467
|
|
|
* |
|
468
|
|
|
* @return bool |
|
469
|
|
|
*/ |
|
470
|
1 |
|
public function delete() |
|
471
|
|
|
{ |
|
472
|
1 |
|
return self::execute( |
|
473
|
1 |
|
$this->eq($this->primaryKeyName, $this->{$this->primaryKeyName})->_buildSql( |
|
474
|
|
|
array( |
|
475
|
1 |
|
'delete', |
|
476
|
1 |
|
'from', |
|
477
|
1 |
|
'where', |
|
478
|
|
|
) |
|
479
|
1 |
|
), |
|
480
|
1 |
|
$this->params |
|
481
|
1 |
|
); |
|
482
|
|
|
} |
|
483
|
|
|
|
|
484
|
|
|
/** |
|
485
|
|
|
* @param string $primaryKeyName |
|
486
|
|
|
* |
|
487
|
|
|
* @return $this |
|
488
|
|
|
*/ |
|
489
|
|
|
public function setPrimaryKeyName($primaryKeyName) |
|
490
|
|
|
{ |
|
491
|
|
|
$this->primaryKeyName = $primaryKeyName; |
|
492
|
|
|
|
|
493
|
|
|
return $this; |
|
494
|
|
|
} |
|
495
|
|
|
|
|
496
|
|
|
/** |
|
497
|
|
|
* @param string $table |
|
498
|
|
|
*/ |
|
499
|
|
|
public function setTable($table) |
|
500
|
|
|
{ |
|
501
|
|
|
$this->table = $table; |
|
502
|
|
|
} |
|
503
|
|
|
|
|
504
|
|
|
/** |
|
505
|
|
|
* Function to build update SQL, and update current record in database, just write the dirty data into database. |
|
506
|
|
|
* |
|
507
|
|
|
* @return bool|int <p> |
|
508
|
|
|
* If update was successful, it will return the affected rows as int, |
|
509
|
|
|
* otherwise it will return false or true (if there are no dirty data). |
|
510
|
|
|
* </p> |
|
511
|
|
|
*/ |
|
512
|
2 |
|
public function update() |
|
513
|
|
|
{ |
|
514
|
2 |
|
if (count($this->dirty) == 0) { |
|
515
|
|
|
return true; |
|
516
|
|
|
} |
|
517
|
|
|
|
|
518
|
2 |
|
foreach ($this->dirty as $field => $value) { |
|
519
|
2 |
|
$this->addCondition($field, '=', $value, ',', 'set'); |
|
520
|
2 |
|
} |
|
521
|
|
|
|
|
522
|
2 |
|
$result = self::execute( |
|
523
|
2 |
|
$this->eq($this->primaryKeyName, $this->{$this->primaryKeyName})->_buildSql( |
|
524
|
|
|
array( |
|
525
|
2 |
|
'update', |
|
526
|
2 |
|
'set', |
|
527
|
2 |
|
'where', |
|
528
|
|
|
) |
|
529
|
2 |
|
), |
|
530
|
2 |
|
$this->params |
|
531
|
2 |
|
); |
|
532
|
2 |
|
if ($result) { |
|
533
|
2 |
|
$this->resetDirty(); |
|
534
|
2 |
|
$this->reset(); |
|
535
|
|
|
|
|
536
|
2 |
|
return $result; |
|
537
|
|
|
} |
|
538
|
|
|
|
|
539
|
|
|
return false; |
|
540
|
|
|
} |
|
541
|
|
|
|
|
542
|
|
|
/** |
|
543
|
|
|
* Function to build insert SQL, and insert current record into database. |
|
544
|
|
|
* |
|
545
|
|
|
* @return bool|int <p> |
|
546
|
|
|
* If insert was successful, it will return the new id, |
|
547
|
|
|
* otherwise it will return false or true (if there are no dirty data). |
|
548
|
|
|
* </p> |
|
549
|
|
|
*/ |
|
550
|
3 |
|
public function insert() |
|
551
|
|
|
{ |
|
552
|
3 |
|
if (!self::$db instanceof DB) { |
|
553
|
|
|
self::$db = DB::getInstance(); |
|
554
|
|
|
} |
|
555
|
|
|
|
|
556
|
3 |
|
if (count($this->dirty) === 0) { |
|
557
|
|
|
return true; |
|
558
|
|
|
} |
|
559
|
|
|
|
|
560
|
3 |
|
$value = $this->_filterParam($this->dirty); |
|
561
|
3 |
|
$this->insert = new ActiveRecordExpressions( |
|
|
|
|
|
|
562
|
|
|
array( |
|
563
|
3 |
|
'operator' => 'INSERT INTO ' . $this->table, |
|
564
|
3 |
|
'target' => new ActiveRecordExpressionsWrap(array('target' => array_keys($this->dirty))), |
|
565
|
|
|
) |
|
566
|
3 |
|
); |
|
567
|
3 |
|
$this->values = new ActiveRecordExpressions( |
|
|
|
|
|
|
568
|
|
|
array( |
|
569
|
3 |
|
'operator' => 'VALUES', |
|
570
|
3 |
|
'target' => new ActiveRecordExpressionsWrap(array('target' => $value)), |
|
571
|
|
|
) |
|
572
|
3 |
|
); |
|
573
|
|
|
|
|
574
|
3 |
|
$result = self::execute($this->_buildSql(array('insert', 'values')), $this->params); |
|
575
|
3 |
|
if ($result) { |
|
576
|
3 |
|
$this->{$this->primaryKeyName} = $result; |
|
577
|
|
|
|
|
578
|
3 |
|
$this->resetDirty(); |
|
579
|
3 |
|
$this->reset(); |
|
580
|
|
|
|
|
581
|
3 |
|
return $result; |
|
582
|
|
|
} |
|
583
|
|
|
|
|
584
|
|
|
return false; |
|
585
|
|
|
} |
|
586
|
|
|
|
|
587
|
|
|
/** |
|
588
|
|
|
* Helper function to copy an existing active record (and insert it into the database). |
|
589
|
|
|
* |
|
590
|
|
|
* @param bool $insert |
|
591
|
|
|
* |
|
592
|
|
|
* @return $this |
|
593
|
|
|
*/ |
|
594
|
1 |
|
public function copy($insert = true) |
|
595
|
|
|
{ |
|
596
|
1 |
|
$new = clone $this; |
|
597
|
|
|
|
|
598
|
1 |
|
if ($insert) { |
|
599
|
1 |
|
$new->setPrimaryKey(null); |
|
600
|
1 |
|
$id = $new->insert(); |
|
601
|
1 |
|
$new->setPrimaryKey($id); |
|
602
|
1 |
|
} |
|
603
|
|
|
|
|
604
|
1 |
|
return $new; |
|
605
|
|
|
} |
|
606
|
|
|
|
|
607
|
|
|
/** |
|
608
|
|
|
* Helper function to exec sql. |
|
609
|
|
|
* |
|
610
|
|
|
* @param string $sql The SQL need to be execute. |
|
611
|
|
|
* @param array $param The param will be bind to the sql statement. |
|
612
|
|
|
* |
|
613
|
|
|
* @return bool|int|Result <p> |
|
614
|
|
|
* "Result" by "<b>SELECT</b>"-queries<br /> |
|
615
|
|
|
* "int" (insert_id) by "<b>INSERT / REPLACE</b>"-queries<br /> |
|
616
|
|
|
* "int" (affected_rows) by "<b>UPDATE / DELETE</b>"-queries<br /> |
|
617
|
|
|
* "true" by e.g. "DROP"-queries<br /> |
|
618
|
|
|
* "false" on error |
|
619
|
|
|
* </p> |
|
620
|
|
|
*/ |
|
621
|
23 |
|
public static function execute($sql, array $param = array()) |
|
622
|
|
|
{ |
|
623
|
23 |
|
if (!self::$db instanceof DB) { |
|
624
|
1 |
|
self::$db = DB::getInstance(); |
|
625
|
1 |
|
} |
|
626
|
|
|
|
|
627
|
23 |
|
return self::$db->query($sql, $param); |
|
628
|
|
|
} |
|
629
|
|
|
|
|
630
|
|
|
/** |
|
631
|
|
|
* Helper function to query one record by sql and params. |
|
632
|
|
|
* |
|
633
|
|
|
* @param string $sql <p> |
|
634
|
|
|
* The SQL query to find the record. |
|
635
|
|
|
* </p> |
|
636
|
|
|
* @param array $param <p> |
|
637
|
|
|
* The param will be bind to the $sql query. |
|
638
|
|
|
* </p> |
|
639
|
|
|
* @param ActiveRecord|null $obj <p> |
|
640
|
|
|
* The object, if find record in database, we will assign the attributes into |
|
641
|
|
|
* this object. |
|
642
|
|
|
* </p> |
|
643
|
|
|
* @param bool $single <p> |
|
644
|
|
|
* If set to true, we will find record and fetch in current object, otherwise |
|
645
|
|
|
* will find all records. |
|
646
|
|
|
* </p> |
|
647
|
|
|
* |
|
648
|
|
|
* @return bool|$this|array |
|
649
|
|
|
*/ |
|
650
|
17 |
|
public static function query($sql, array $param = array(), ActiveRecord $obj = null, $single = false) |
|
651
|
|
|
{ |
|
652
|
17 |
|
$result = self::execute($sql, $param); |
|
653
|
|
|
|
|
654
|
17 |
|
if (!$result) { |
|
655
|
|
|
return false; |
|
656
|
|
|
} |
|
657
|
|
|
|
|
658
|
17 |
|
$useObject = is_object($obj); |
|
659
|
17 |
|
if ($useObject === true) { |
|
660
|
17 |
|
$called_class = $obj; |
|
661
|
17 |
|
} else { |
|
662
|
|
|
$called_class = get_called_class(); |
|
663
|
|
|
} |
|
664
|
|
|
|
|
665
|
17 |
|
self::setNewDataAreDirty(false); |
|
666
|
|
|
|
|
667
|
17 |
|
if ($single) { |
|
668
|
11 |
|
$return = $result->fetchObject($called_class, null, true); |
|
|
|
|
|
|
669
|
11 |
|
} else { |
|
670
|
8 |
|
$return = $result->fetchAllObject($called_class, null); |
|
|
|
|
|
|
671
|
|
|
} |
|
672
|
|
|
|
|
673
|
17 |
|
self::setNewDataAreDirty(true); |
|
674
|
|
|
|
|
675
|
17 |
|
return $return; |
|
676
|
|
|
} |
|
677
|
|
|
|
|
678
|
|
|
/** |
|
679
|
|
|
* Helper function to get relation of this object. |
|
680
|
|
|
* There was three types of relations: {BELONGS_TO, HAS_ONE, HAS_MANY} |
|
681
|
|
|
* |
|
682
|
|
|
* @param string $name The name of the relation, the array key when defind the relation. |
|
683
|
|
|
* |
|
684
|
|
|
* @return mixed |
|
685
|
|
|
* |
|
686
|
|
|
* @throws ActiveRecordException <p>If the relation can't be found .</p> |
|
687
|
|
|
*/ |
|
688
|
3 |
|
protected function &getRelation($name) |
|
689
|
|
|
{ |
|
690
|
3 |
|
$relation = $this->relations[$name]; |
|
691
|
|
|
if ( |
|
692
|
|
|
$relation instanceof self |
|
693
|
3 |
|
|| |
|
694
|
|
|
( |
|
695
|
2 |
|
is_array($relation) |
|
696
|
2 |
|
&& |
|
697
|
2 |
|
$relation[0] instanceof self |
|
698
|
2 |
|
) |
|
699
|
3 |
|
) { |
|
700
|
3 |
|
return $relation; |
|
701
|
|
|
} |
|
702
|
|
|
|
|
703
|
|
|
/* @var $obj ActiveRecord */ |
|
704
|
2 |
|
$obj = new $relation[1]; |
|
705
|
|
|
|
|
706
|
2 |
|
$this->relations[$name] = $obj; |
|
707
|
2 |
|
if (isset($relation[3]) && is_array($relation[3])) { |
|
708
|
1 |
|
foreach ((array)$relation[3] as $func => $args) { |
|
709
|
1 |
|
call_user_func_array(array($obj, $func), (array)$args); |
|
710
|
1 |
|
} |
|
711
|
1 |
|
} |
|
712
|
|
|
|
|
713
|
2 |
|
$backref = isset($relation[4]) ? $relation[4] : ''; |
|
714
|
|
|
if ( |
|
715
|
2 |
|
(!$relation instanceof self) |
|
716
|
2 |
|
&& |
|
717
|
2 |
|
self::HAS_ONE == $relation[0] |
|
718
|
2 |
|
) { |
|
719
|
|
|
|
|
720
|
1 |
|
$this->relations[$name] = $obj->eq($relation[2], $this->{$this->primaryKeyName})->fetch(); |
|
721
|
|
|
|
|
722
|
1 |
|
if ($backref) { |
|
723
|
|
|
$this->relations[$name] && $backref && $obj->__set($backref, $this); |
|
724
|
|
|
} |
|
725
|
|
|
|
|
726
|
1 |
|
} elseif ( |
|
727
|
2 |
|
is_array($relation) |
|
728
|
2 |
|
&& |
|
729
|
2 |
|
self::HAS_MANY == $relation[0] |
|
730
|
2 |
|
) { |
|
731
|
|
|
|
|
732
|
2 |
|
$this->relations[$name] = $obj->eq($relation[2], $this->{$this->primaryKeyName})->fetchAll(); |
|
733
|
2 |
|
if ($backref) { |
|
734
|
1 |
|
foreach ($this->relations[$name] as $o) { |
|
|
|
|
|
|
735
|
1 |
|
$o->__set($backref, $this); |
|
736
|
1 |
|
} |
|
737
|
1 |
|
} |
|
738
|
|
|
|
|
739
|
2 |
|
} elseif ( |
|
740
|
2 |
|
(!$relation instanceof self) |
|
741
|
2 |
|
&& |
|
742
|
2 |
|
self::BELONGS_TO == $relation[0] |
|
743
|
2 |
|
) { |
|
744
|
|
|
|
|
745
|
2 |
|
$this->relations[$name] = $obj->eq($obj->primaryKeyName, $this->{$relation[2]})->fetch(); |
|
746
|
|
|
|
|
747
|
2 |
|
if ($backref) { |
|
748
|
1 |
|
$this->relations[$name] && $backref && $obj->__set($backref, $this); |
|
749
|
1 |
|
} |
|
750
|
|
|
|
|
751
|
2 |
|
} else { |
|
752
|
|
|
throw new ActiveRecordException("Relation $name not found."); |
|
753
|
|
|
} |
|
754
|
|
|
|
|
755
|
2 |
|
return $this->relations[$name]; |
|
756
|
|
|
} |
|
757
|
|
|
|
|
758
|
|
|
/** |
|
759
|
|
|
* Helper function to build SQL with sql parts. |
|
760
|
|
|
* |
|
761
|
|
|
* @param string $n The SQL part will be build. |
|
762
|
|
|
* @param int $i The index of $n in $sql array. |
|
763
|
|
|
* @param ActiveRecord $o The reference to $this |
|
764
|
|
|
*/ |
|
765
|
20 |
|
private function _buildSqlCallback(&$n, $i, $o) |
|
766
|
|
|
{ |
|
767
|
|
|
if ( |
|
768
|
|
|
'select' === $n |
|
769
|
20 |
|
&& |
|
770
|
15 |
|
null === $o->$n |
|
771
|
20 |
|
) { |
|
772
|
|
|
|
|
773
|
14 |
|
$n = strtoupper($n) . ' ' . $o->table . '.*'; |
|
774
|
|
|
|
|
775
|
14 |
|
} elseif ( |
|
776
|
|
|
( |
|
777
|
|
|
'update' === $n |
|
778
|
20 |
|
|| |
|
779
|
|
|
'from' === $n |
|
780
|
20 |
|
) |
|
781
|
20 |
|
&& |
|
782
|
17 |
|
null === $o->$n |
|
783
|
20 |
|
) { |
|
784
|
|
|
|
|
785
|
17 |
|
$n = strtoupper($n) . ' ' . $o->table; |
|
786
|
|
|
|
|
787
|
20 |
|
} elseif ('delete' === $n) { |
|
788
|
|
|
|
|
789
|
1 |
|
$n = strtoupper($n) . ' '; |
|
790
|
|
|
|
|
791
|
1 |
|
} else { |
|
792
|
|
|
|
|
793
|
20 |
|
$n = (null !== $o->$n) ? $o->$n . ' ' : ''; |
|
794
|
|
|
|
|
795
|
|
|
} |
|
796
|
20 |
|
} |
|
797
|
|
|
|
|
798
|
|
|
/** |
|
799
|
|
|
* Helper function to build SQL with sql parts. |
|
800
|
|
|
* |
|
801
|
|
|
* @param array $sqls The SQL part will be build. |
|
802
|
|
|
* |
|
803
|
|
|
* @return string |
|
804
|
|
|
*/ |
|
805
|
20 |
|
protected function _buildSql($sqls = array()) |
|
806
|
|
|
{ |
|
807
|
20 |
|
array_walk($sqls, array($this, '_buildSqlCallback'), $this); |
|
808
|
|
|
|
|
809
|
|
|
// DEBUG |
|
810
|
|
|
//echo 'SQL: ', implode(' ', $sqls), "\n", 'PARAMS: ', implode(', ', $this->params), "\n"; |
|
811
|
|
|
|
|
812
|
20 |
|
return implode(' ', $sqls); |
|
813
|
|
|
} |
|
814
|
|
|
|
|
815
|
|
|
/** |
|
816
|
|
|
* Magic function to make calls witch in function mapping stored in $operators and $sqlPart. |
|
817
|
|
|
* also can call function of DB object. |
|
818
|
|
|
* |
|
819
|
|
|
* @param string $name function name |
|
820
|
|
|
* @param array $args The arguments of the function. |
|
821
|
|
|
* |
|
822
|
|
|
* @return $this|mixed Return the result of callback or the current object to make chain method calls. |
|
823
|
|
|
* |
|
824
|
|
|
* @throws ActiveRecordException |
|
825
|
|
|
*/ |
|
826
|
16 |
|
public function __call($name, $args) |
|
827
|
|
|
{ |
|
828
|
16 |
|
if (!self::$db instanceof DB) { |
|
829
|
|
|
self::$db = DB::getInstance(); |
|
830
|
|
|
} |
|
831
|
|
|
|
|
832
|
16 |
|
$nameTmp = strtolower($name); |
|
833
|
|
|
|
|
834
|
16 |
|
if (array_key_exists($nameTmp, self::$operators)) { |
|
835
|
|
|
|
|
836
|
14 |
|
$this->addCondition( |
|
837
|
14 |
|
$args[0], |
|
838
|
14 |
|
self::$operators[$nameTmp], |
|
839
|
14 |
|
isset($args[1]) ? $args[1] : null, |
|
840
|
14 |
|
(is_string(end($args)) && 'or' === strtolower(end($args))) ? 'OR' : 'AND' |
|
841
|
14 |
|
); |
|
842
|
|
|
|
|
843
|
16 |
|
} elseif (array_key_exists($nameTmp = str_replace('by', '', $nameTmp), $this->sqlParts)) { |
|
844
|
|
|
|
|
845
|
11 |
|
$this->$name = new ActiveRecordExpressions( |
|
846
|
|
|
array( |
|
847
|
11 |
|
'operator' => $this->sqlParts[$nameTmp], |
|
848
|
11 |
|
'target' => implode(', ', $args), |
|
849
|
|
|
) |
|
850
|
11 |
|
); |
|
851
|
|
|
|
|
852
|
11 |
|
} elseif (is_callable($callback = array(self::$db, $name))) { |
|
853
|
|
|
|
|
854
|
|
|
return call_user_func_array($callback, $args); |
|
855
|
|
|
|
|
856
|
|
|
} else { |
|
857
|
|
|
|
|
858
|
|
|
throw new ActiveRecordException("Method $name not exist."); |
|
859
|
|
|
|
|
860
|
|
|
} |
|
861
|
|
|
|
|
862
|
16 |
|
return $this; |
|
863
|
|
|
} |
|
864
|
|
|
|
|
865
|
|
|
/** |
|
866
|
|
|
* Make wrap when build the SQL expressions of WHERE. |
|
867
|
|
|
* |
|
868
|
|
|
* @param string $op If give this param will build one WrapExpressions include the stored expressions add into WHERE. |
|
869
|
|
|
* otherwise wil stored the expressions into array. |
|
870
|
|
|
* |
|
871
|
|
|
* @return $this |
|
872
|
|
|
*/ |
|
873
|
1 |
|
public function wrap($op = null) |
|
874
|
|
|
{ |
|
875
|
1 |
|
if (1 === func_num_args()) { |
|
876
|
1 |
|
$this->wrap = false; |
|
|
|
|
|
|
877
|
1 |
|
if (is_array($this->expressions) && count($this->expressions) > 0) { |
|
|
|
|
|
|
878
|
1 |
|
$this->_addCondition( |
|
879
|
1 |
|
new ActiveRecordExpressionsWrap( |
|
880
|
|
|
array( |
|
881
|
1 |
|
'delimiter' => ' ', |
|
882
|
1 |
|
'target' => $this->expressions, |
|
|
|
|
|
|
883
|
|
|
) |
|
884
|
1 |
|
), 'or' === strtolower($op) ? 'OR' : 'AND' |
|
885
|
1 |
|
); |
|
886
|
1 |
|
} |
|
887
|
1 |
|
$this->expressions = array(); |
|
|
|
|
|
|
888
|
1 |
|
} else { |
|
889
|
1 |
|
$this->wrap = true; |
|
|
|
|
|
|
890
|
|
|
} |
|
891
|
|
|
|
|
892
|
1 |
|
return $this; |
|
893
|
|
|
} |
|
894
|
|
|
|
|
895
|
|
|
/** |
|
896
|
|
|
* Helper function to build place holder when make SQL expressions. |
|
897
|
|
|
* |
|
898
|
|
|
* @param mixed $value The value will bind to SQL, just store it in $this->params. |
|
899
|
|
|
* |
|
900
|
|
|
* @return mixed $value |
|
901
|
|
|
*/ |
|
902
|
17 |
|
protected function _filterParam($value) |
|
903
|
|
|
{ |
|
904
|
17 |
|
if (is_array($value)) { |
|
905
|
7 |
|
foreach ($value as $key => $val) { |
|
906
|
7 |
|
$this->params[$value[$key] = self::PREFIX . ++self::$count] = $val; |
|
907
|
7 |
|
} |
|
908
|
17 |
|
} elseif (is_string($value)) { |
|
909
|
3 |
|
$this->params[$ph = self::PREFIX . ++self::$count] = $value; |
|
910
|
3 |
|
$value = $ph; |
|
911
|
3 |
|
} |
|
912
|
|
|
|
|
913
|
17 |
|
return $value; |
|
914
|
|
|
} |
|
915
|
|
|
|
|
916
|
|
|
/** |
|
917
|
|
|
* Helper function to add condition into WHERE. |
|
918
|
|
|
* create the SQL Expressions. |
|
919
|
|
|
* |
|
920
|
|
|
* @param string $field The field name, the source of Expressions |
|
921
|
|
|
* @param string $operator |
|
922
|
|
|
* @param mixed $value The target of the Expressions |
|
923
|
|
|
* @param string $op The operator to concat this Expressions into WHERE or SET statement. |
|
924
|
|
|
* @param string $name The Expression will contact to. |
|
925
|
|
|
*/ |
|
926
|
14 |
|
public function addCondition($field, $operator, $value, $op = 'AND', $name = 'where') |
|
927
|
|
|
{ |
|
928
|
14 |
|
$value = $this->_filterParam($value); |
|
929
|
14 |
|
$exp = new ActiveRecordExpressions( |
|
930
|
|
|
array( |
|
931
|
14 |
|
'source' => ('where' == $name ? $this->table . '.' : '') . $field, |
|
932
|
14 |
|
'operator' => $operator, |
|
933
|
14 |
|
'target' => is_array($value) |
|
934
|
14 |
|
? new ActiveRecordExpressionsWrap( |
|
935
|
4 |
|
'between' === strtolower($operator) |
|
936
|
4 |
|
? array('target' => $value, 'start' => ' ', 'end' => ' ', 'delimiter' => ' AND ') |
|
937
|
4 |
|
: array('target' => $value) |
|
938
|
14 |
|
) : $value, |
|
939
|
|
|
) |
|
940
|
14 |
|
); |
|
941
|
14 |
|
if ($exp) { |
|
942
|
14 |
|
if (!$this->wrap) { |
|
|
|
|
|
|
943
|
14 |
|
$this->_addCondition($exp, $op, $name); |
|
944
|
14 |
|
} else { |
|
945
|
1 |
|
$this->_addExpression($exp, $op); |
|
946
|
|
|
} |
|
947
|
14 |
|
} |
|
948
|
14 |
|
} |
|
949
|
|
|
|
|
950
|
|
|
/** |
|
951
|
|
|
* helper function to add condition into JOIN. |
|
952
|
|
|
* create the SQL Expressions. |
|
953
|
|
|
* |
|
954
|
|
|
* @param string $table The join table name |
|
955
|
|
|
* @param string $on The condition of ON |
|
956
|
|
|
* @param string $type The join type, like "LEFT", "INNER", "OUTER" |
|
957
|
|
|
* |
|
958
|
|
|
* @return $this |
|
959
|
|
|
*/ |
|
960
|
1 |
|
public function join($table, $on, $type = 'LEFT') |
|
961
|
|
|
{ |
|
962
|
1 |
|
$this->join = new ActiveRecordExpressions( |
|
|
|
|
|
|
963
|
|
|
array( |
|
964
|
1 |
|
'source' => $this->join ?: '', |
|
|
|
|
|
|
965
|
1 |
|
'operator' => $type . ' JOIN', |
|
966
|
1 |
|
'target' => new ActiveRecordExpressions( |
|
967
|
1 |
|
array('source' => $table, 'operator' => 'ON', 'target' => $on) |
|
968
|
1 |
|
), |
|
969
|
|
|
) |
|
970
|
1 |
|
); |
|
971
|
|
|
|
|
972
|
1 |
|
return $this; |
|
973
|
|
|
} |
|
974
|
|
|
|
|
975
|
|
|
/** |
|
976
|
|
|
* helper function to make wrapper. Stored the expression in to array. |
|
977
|
|
|
* |
|
978
|
|
|
* @param ActiveRecordExpressions $exp The expression will be stored. |
|
979
|
|
|
* @param string $operator The operator to concat this Expressions into WHERE statment. |
|
980
|
|
|
*/ |
|
981
|
1 |
|
protected function _addExpression($exp, $operator) |
|
982
|
|
|
{ |
|
983
|
1 |
|
if (!is_array($this->expressions) || count($this->expressions) == 0) { |
|
|
|
|
|
|
984
|
1 |
|
$this->expressions = array($exp); |
|
|
|
|
|
|
985
|
1 |
|
} else { |
|
986
|
1 |
|
$this->expressions[] = new ActiveRecordExpressions(array('operator' => $operator, 'target' => $exp)); |
|
|
|
|
|
|
987
|
|
|
} |
|
988
|
1 |
|
} |
|
989
|
|
|
|
|
990
|
|
|
/** |
|
991
|
|
|
* helper function to add condition into WHERE. |
|
992
|
|
|
* |
|
993
|
|
|
* @param ActiveRecordExpressions $exp The expression will be concat into WHERE or SET statment. |
|
994
|
|
|
* @param string $operator the operator to concat this Expressions into WHERE or SET statment. |
|
995
|
|
|
* @param string $name The Expression will contact to. |
|
996
|
|
|
*/ |
|
997
|
14 |
|
protected function _addCondition($exp, $operator, $name = 'where') |
|
998
|
|
|
{ |
|
999
|
14 |
|
if (!$this->$name) { |
|
1000
|
14 |
|
$this->$name = new ActiveRecordExpressions(array('operator' => strtoupper($name), 'target' => $exp)); |
|
1001
|
14 |
|
} else { |
|
1002
|
4 |
|
$this->$name->target = new ActiveRecordExpressions( |
|
1003
|
|
|
array( |
|
1004
|
4 |
|
'source' => $this->$name->target, |
|
1005
|
4 |
|
'operator' => $operator, |
|
1006
|
4 |
|
'target' => $exp, |
|
1007
|
|
|
) |
|
1008
|
4 |
|
); |
|
1009
|
|
|
} |
|
1010
|
14 |
|
} |
|
1011
|
|
|
|
|
1012
|
|
|
/** |
|
1013
|
|
|
* @return array |
|
1014
|
|
|
*/ |
|
1015
|
1 |
|
public function getDirty() |
|
1016
|
|
|
{ |
|
1017
|
1 |
|
return $this->dirty; |
|
1018
|
|
|
} |
|
1019
|
|
|
|
|
1020
|
|
|
/** |
|
1021
|
|
|
* @return bool |
|
1022
|
|
|
*/ |
|
1023
|
|
|
public static function isNewDataAreDirty() |
|
1024
|
|
|
{ |
|
1025
|
|
|
return self::$new_data_are_dirty; |
|
1026
|
|
|
} |
|
1027
|
|
|
|
|
1028
|
|
|
/** |
|
1029
|
|
|
* @param bool $bool |
|
1030
|
|
|
*/ |
|
1031
|
17 |
|
public static function setNewDataAreDirty($bool) |
|
1032
|
|
|
{ |
|
1033
|
17 |
|
self::$new_data_are_dirty = (bool)$bool; |
|
1034
|
17 |
|
} |
|
1035
|
|
|
|
|
1036
|
|
|
/** |
|
1037
|
|
|
* Magic function to SET values of the current object. |
|
1038
|
|
|
* |
|
1039
|
|
|
* @param mixed $var |
|
1040
|
|
|
* @param mixed $val |
|
1041
|
|
|
*/ |
|
1042
|
22 |
|
public function __set($var, $val) |
|
1043
|
|
|
{ |
|
1044
|
|
|
if ( |
|
1045
|
22 |
|
array_key_exists($var, $this->sqlExpressions) |
|
1046
|
|
|
|| |
|
1047
|
22 |
|
array_key_exists($var, $this->defaultSqlExpressions) |
|
1048
|
22 |
|
) { |
|
1049
|
|
|
|
|
1050
|
19 |
|
$this->sqlExpressions[$var] = $val; |
|
1051
|
|
|
|
|
1052
|
19 |
|
} elseif ( |
|
1053
|
19 |
|
array_key_exists($var, $this->relations) |
|
1054
|
19 |
|
&& |
|
1055
|
|
|
$val instanceof self |
|
1056
|
19 |
|
) { |
|
1057
|
|
|
|
|
1058
|
1 |
|
$this->relations[$var] = $val; |
|
1059
|
|
|
|
|
1060
|
1 |
|
} else { |
|
1061
|
|
|
|
|
1062
|
19 |
|
$this->array[$var] = $val; |
|
1063
|
|
|
|
|
1064
|
19 |
|
if (self::$new_data_are_dirty === true) { |
|
1065
|
6 |
|
$this->dirty[$var] = $val; |
|
1066
|
6 |
|
} |
|
1067
|
|
|
|
|
1068
|
|
|
} |
|
1069
|
22 |
|
} |
|
1070
|
|
|
|
|
1071
|
|
|
/** |
|
1072
|
|
|
* Magic function to UNSET values of the current object. |
|
1073
|
|
|
* |
|
1074
|
|
|
* @param mixed $var |
|
1075
|
|
|
*/ |
|
1076
|
1 |
|
public function __unset($var) |
|
1077
|
|
|
{ |
|
1078
|
1 |
|
if (array_key_exists($var, $this->sqlExpressions)) { |
|
1079
|
|
|
unset($this->sqlExpressions[$var]); |
|
1080
|
|
|
} |
|
1081
|
|
|
|
|
1082
|
1 |
|
if (isset($this->array[$var])) { |
|
1083
|
1 |
|
unset($this->array[$var]); |
|
1084
|
1 |
|
} |
|
1085
|
|
|
|
|
1086
|
1 |
|
if (isset($this->dirty[$var])) { |
|
1087
|
1 |
|
unset($this->dirty[$var]); |
|
1088
|
1 |
|
} |
|
1089
|
1 |
|
} |
|
1090
|
|
|
|
|
1091
|
|
|
/** |
|
1092
|
|
|
* Helper function for "GROUP BY". |
|
1093
|
|
|
* |
|
1094
|
|
|
* @param array $args |
|
1095
|
|
|
* @param null $dummy <p>only needed for API compatibility with Arrayy</p> |
|
1096
|
|
|
* |
|
1097
|
|
|
* @return $this |
|
1098
|
|
|
*/ |
|
1099
|
|
|
public function group($args, $dummy = null) |
|
1100
|
|
|
{ |
|
1101
|
|
|
$this->__call('group', func_get_args()); |
|
1102
|
|
|
|
|
1103
|
|
|
return $this; |
|
1104
|
|
|
} |
|
1105
|
|
|
|
|
1106
|
|
|
/** |
|
1107
|
|
|
* Helper function for "ORDER BY". |
|
1108
|
|
|
* |
|
1109
|
|
|
* @param $args ... |
|
1110
|
|
|
* |
|
1111
|
|
|
* @return $this |
|
1112
|
|
|
*/ |
|
1113
|
2 |
|
public function order($args) |
|
|
|
|
|
|
1114
|
|
|
{ |
|
1115
|
2 |
|
$this->__call('order', func_get_args()); |
|
1116
|
|
|
|
|
1117
|
2 |
|
return $this; |
|
1118
|
|
|
} |
|
1119
|
|
|
|
|
1120
|
|
|
/** |
|
1121
|
|
|
* Magic function to GET the values of current object. |
|
1122
|
|
|
* |
|
1123
|
|
|
* @param $var |
|
1124
|
|
|
* |
|
1125
|
|
|
* @return mixed |
|
1126
|
|
|
*/ |
|
1127
|
22 |
|
public function &__get($var) |
|
1128
|
|
|
{ |
|
1129
|
22 |
|
if (array_key_exists($var, $this->sqlExpressions)) { |
|
1130
|
19 |
|
return $this->sqlExpressions[$var]; |
|
1131
|
|
|
} |
|
1132
|
|
|
|
|
1133
|
22 |
|
if (array_key_exists($var, $this->relations)) { |
|
1134
|
3 |
|
return $this->getRelation($var); |
|
|
|
|
|
|
1135
|
|
|
} |
|
1136
|
|
|
|
|
1137
|
22 |
|
if (isset($this->dirty[$var])) { |
|
1138
|
3 |
|
return $this->dirty[$var]; |
|
1139
|
|
|
} |
|
1140
|
|
|
|
|
1141
|
22 |
|
return parent::__get($var); |
|
1142
|
|
|
} |
|
1143
|
|
|
} |
|
1144
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.