1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Anax\DatabaseActiveRecord; |
4
|
|
|
|
5
|
|
|
use Anax\DatabaseActiveRecord\Exception\ActiveRecordException; |
6
|
|
|
use Anax\DatabaseQueryBuilder\DatabaseQueryBuilder; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* An implementation of the Active Record pattern to be used as |
10
|
|
|
* base class for database driven models. |
11
|
|
|
*/ |
12
|
|
|
class ActiveRecordModel |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* @var DatabaseQueryBuilder $db the object for persistent |
16
|
|
|
* storage. |
17
|
|
|
*/ |
18
|
|
|
protected $db = null; |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var string $tableName name of the database table. |
24
|
|
|
*/ |
25
|
|
|
protected $tableName = null; |
26
|
|
|
|
27
|
|
|
|
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var string $tableIdColumn name of the id column in the database table. |
31
|
|
|
*/ |
32
|
|
|
protected $tableIdColumn = "id"; |
33
|
|
|
|
34
|
|
|
|
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Set the database object to use for accessing storage. |
38
|
|
|
* |
39
|
|
|
* @param DatabaseQueryBuilder $db as database access object. |
40
|
|
|
* |
41
|
|
|
* @return void |
42
|
|
|
*/ |
43
|
7 |
|
public function setDb(DatabaseQueryBuilder $db) |
44
|
|
|
{ |
45
|
7 |
|
$this->db = $db; |
46
|
7 |
|
} |
47
|
|
|
|
48
|
|
|
|
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Check if database is injected or throw an exception. |
52
|
|
|
* |
53
|
|
|
* @throws ActiveRecordException when database is not set. |
54
|
|
|
* |
55
|
|
|
* @return void |
56
|
|
|
*/ |
57
|
8 |
|
protected function checkDb() |
58
|
|
|
{ |
59
|
8 |
|
if (!$this->db) { |
60
|
1 |
|
throw new ActiveRecordException("Missing \$db, did you forget to inject/set is?"); |
61
|
|
|
} |
62
|
7 |
|
} |
63
|
|
|
|
64
|
|
|
|
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Get essential object properties. |
68
|
|
|
* |
69
|
|
|
* @return array with object properties. |
70
|
|
|
*/ |
71
|
7 |
|
protected function getProperties() |
72
|
|
|
{ |
73
|
7 |
|
$properties = get_object_vars($this); |
74
|
|
|
unset( |
75
|
7 |
|
$properties['tableName'], |
76
|
7 |
|
$properties['db'], |
77
|
7 |
|
$properties['di'], |
78
|
7 |
|
$properties['tableIdColumn'] |
79
|
|
|
); |
80
|
7 |
|
return $properties; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
|
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Find and return first object found by search criteria and use |
87
|
|
|
* its data to populate this instance. |
88
|
|
|
* |
89
|
|
|
* @param string $column to use in where statement. |
90
|
|
|
* @param mixed $value to use in where statement. |
91
|
|
|
* |
92
|
|
|
* @return this |
93
|
|
|
*/ |
94
|
1 |
|
public function find($column, $value) : object |
95
|
|
|
{ |
96
|
1 |
|
return $this->findWhere("$column = ?", $value); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
|
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Find and return first object by its tableIdColumn and use |
103
|
|
|
* its data to populate this instance. |
104
|
|
|
* |
105
|
|
|
* @param integer $id to find or use $this->{$this->tableIdColumn} |
106
|
|
|
* as default. |
107
|
|
|
* |
108
|
|
|
* @return this |
109
|
|
|
*/ |
110
|
5 |
|
public function findById($id = null) : object |
111
|
|
|
{ |
112
|
5 |
|
$id = $id ?: $this->{$this->tableIdColumn}; |
113
|
5 |
|
return $this->findWhere("{$this->tableIdColumn} = ?", $id); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
|
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Find and return first object found by search criteria and use |
120
|
|
|
* its data to populate this instance. |
121
|
|
|
* |
122
|
|
|
* The search criteria `$where` of can be set up like this: |
123
|
|
|
* `id = ?` |
124
|
|
|
* `id1 = ? and id2 = ?` |
125
|
|
|
* |
126
|
|
|
* The `$value` can be a single value or an array of values. |
127
|
|
|
* |
128
|
|
|
* @param string $where to use in where statement. |
129
|
|
|
* @param mixed $value to use in where statement. |
130
|
|
|
* |
131
|
|
|
* @return this |
132
|
|
|
*/ |
133
|
5 |
|
public function findWhere($where, $value) : object |
134
|
|
|
{ |
135
|
5 |
|
$this->checkDb(); |
136
|
5 |
|
$params = is_array($value) ? $value : [$value]; |
137
|
5 |
|
$this->db->connect() |
138
|
5 |
|
->select() |
139
|
5 |
|
->from($this ->tableName) |
140
|
5 |
|
->where($where) |
141
|
5 |
|
->execute($params) |
142
|
5 |
|
->fetchInto($this); |
143
|
5 |
|
return $this; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
|
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Find and return all. |
150
|
|
|
* |
151
|
|
|
* @return array of object of this class |
152
|
|
|
*/ |
153
|
1 |
|
public function findAll() |
154
|
|
|
{ |
155
|
1 |
|
$this->checkDb(); |
156
|
1 |
|
return $this->db->connect() |
157
|
1 |
|
->select() |
158
|
1 |
|
->from($this->tableName) |
159
|
1 |
|
->execute() |
160
|
1 |
|
->fetchAllClass(get_class($this)); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
|
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Find and return all matching the search criteria. |
167
|
|
|
* |
168
|
|
|
* The search criteria `$where` of can be set up like this: |
169
|
|
|
* `id = ?` |
170
|
|
|
* `id IN [?, ?]` |
171
|
|
|
* |
172
|
|
|
* The `$value` can be a single value or an array of values. |
173
|
|
|
* |
174
|
|
|
* @param string $where to use in where statement. |
175
|
|
|
* @param mixed $value to use in where statement. |
176
|
|
|
* |
177
|
|
|
* @return array of object of this class |
178
|
|
|
*/ |
179
|
1 |
|
public function findAllWhere($where, $value) |
180
|
|
|
{ |
181
|
1 |
|
$this->checkDb(); |
182
|
1 |
|
$params = is_array($value) ? $value : [$value]; |
183
|
1 |
|
return $this->db->connect() |
184
|
1 |
|
->select() |
185
|
1 |
|
->from($this->tableName) |
186
|
1 |
|
->where($where) |
187
|
1 |
|
->execute($params) |
188
|
1 |
|
->fetchAllClass(get_class($this)); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
|
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Save current object/row, insert if id is missing and do an |
195
|
|
|
* update if the id exists. |
196
|
|
|
* |
197
|
|
|
* @return void |
198
|
|
|
*/ |
199
|
8 |
|
public function save() |
200
|
|
|
{ |
201
|
8 |
|
if (isset($this->{$this->tableIdColumn})) { |
202
|
2 |
|
return $this->update(); |
|
|
|
|
203
|
|
|
} |
204
|
|
|
|
205
|
8 |
|
return $this->create(); |
|
|
|
|
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
|
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Save/update current object/row using a custom where-statement. |
212
|
|
|
* |
213
|
|
|
* The criteria `$where` of can be set up like this: |
214
|
|
|
* `id = ?` |
215
|
|
|
* `id1 = ? AND id2 = ?` |
216
|
|
|
* |
217
|
|
|
* The `$value` can be a single value or an array of values. |
218
|
|
|
* |
219
|
|
|
* @param string $where to use in where statement. |
220
|
|
|
* @param mixed $value to use in where statement. |
221
|
|
|
* |
222
|
|
|
* @return void |
223
|
|
|
*/ |
224
|
1 |
|
public function saveWhere($where, $value) |
225
|
|
|
{ |
226
|
1 |
|
return $this->updateWhere($where, $value); |
|
|
|
|
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
|
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Create new row. |
233
|
|
|
* |
234
|
|
|
* @return void |
235
|
|
|
*/ |
236
|
8 |
|
protected function create() |
237
|
|
|
{ |
238
|
8 |
|
$this->checkDb(); |
239
|
7 |
|
$properties = $this->getProperties(); |
240
|
7 |
|
unset($properties[$this->tableIdColumn]); |
241
|
7 |
|
$columns = array_keys($properties); |
242
|
7 |
|
$values = array_values($properties); |
243
|
|
|
|
244
|
7 |
|
$this->db->connect() |
245
|
7 |
|
->insert($this->tableName, $columns) |
246
|
7 |
|
->execute($values); |
247
|
|
|
|
248
|
7 |
|
$this->{$this->tableIdColumn} = $this->db->lastInsertId(); |
249
|
7 |
|
} |
250
|
|
|
|
251
|
|
|
|
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Update row using $tableIdColumn as where. |
255
|
|
|
* |
256
|
|
|
* @return void |
257
|
|
|
*/ |
258
|
2 |
|
protected function update() |
259
|
|
|
{ |
260
|
2 |
|
$this->checkDb(); |
261
|
2 |
|
$properties = $this->getProperties(); |
262
|
2 |
|
unset($properties[$this->tableIdColumn]); |
263
|
2 |
|
$columns = array_keys($properties); |
264
|
2 |
|
$values = array_values($properties); |
265
|
2 |
|
$values[] = $this->{$this->tableIdColumn}; |
266
|
|
|
|
267
|
2 |
|
$this->db->connect() |
268
|
2 |
|
->update($this->tableName, $columns) |
269
|
2 |
|
->where("{$this->tableIdColumn} = ?") |
270
|
2 |
|
->execute($values); |
271
|
2 |
|
} |
272
|
|
|
|
273
|
|
|
|
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Update row using a custom where-statement. |
277
|
|
|
* |
278
|
|
|
* The criteria `$where` of can be set up like this: |
279
|
|
|
* `id = ?` |
280
|
|
|
* `id1 = ? AND id2 = ?` |
281
|
|
|
* `id IN (?, ?)` |
282
|
|
|
* |
283
|
|
|
* The `$value` can be a single value or an array of values. |
284
|
|
|
* |
285
|
|
|
* @param string $where to use in where statement. |
286
|
|
|
* @param mixed $value to use in where statement. |
287
|
|
|
* |
288
|
|
|
* @return void |
289
|
|
|
*/ |
290
|
1 |
|
protected function updateWhere($where, $value) |
291
|
|
|
{ |
292
|
1 |
|
$this->checkDb(); |
293
|
1 |
|
$properties = $this->getProperties(); |
294
|
1 |
|
$columns = array_keys($properties); |
295
|
1 |
|
$values = array_values($properties); |
296
|
1 |
|
$values1 = is_array($value) |
297
|
1 |
|
? $value |
298
|
1 |
|
: [$value]; |
299
|
1 |
|
$values = array_merge($values, $values1); |
300
|
|
|
|
301
|
1 |
|
$this->db->connect() |
302
|
1 |
|
->update($this->tableName, $columns) |
303
|
1 |
|
->where($where) |
304
|
1 |
|
->execute($values); |
305
|
1 |
|
} |
306
|
|
|
|
307
|
|
|
|
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* Update row using $tableIdColumn as where and clear value of |
311
|
|
|
* `$tableIdColumn`. |
312
|
|
|
* |
313
|
|
|
* @param integer $id to delete or use $this->{$this->tableIdColumn} |
314
|
|
|
* as default. |
315
|
|
|
* |
316
|
|
|
* @return void |
317
|
|
|
*/ |
318
|
2 |
|
public function delete($id = null) |
319
|
|
|
{ |
320
|
2 |
|
$this->checkDb(); |
321
|
2 |
|
$id = $id ?: $this->{$this->tableIdColumn}; |
322
|
|
|
|
323
|
2 |
|
$this->db->connect() |
324
|
2 |
|
->deleteFrom($this->tableName) |
325
|
2 |
|
->where("{$this->tableIdColumn} = ?") |
326
|
2 |
|
->execute([$id]); |
327
|
|
|
|
328
|
2 |
|
$this->{$this->tableIdColumn} = null; |
329
|
2 |
|
} |
330
|
|
|
|
331
|
|
|
|
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* Delete row using a custom where-statement and leave value of |
335
|
|
|
* `$tableIdColumn` as it is. |
336
|
|
|
* |
337
|
|
|
* The criteria `$where` of can be set up like this: |
338
|
|
|
* `id = ?` |
339
|
|
|
* `id1 = ? AND id2 = ?` |
340
|
|
|
* `id IN (?, ?)` |
341
|
|
|
* |
342
|
|
|
* The `$value` can be a single value or an array of values. |
343
|
|
|
* |
344
|
|
|
* @param string $where to use in where statement. |
345
|
|
|
* @param mixed $value to use in where statement. |
346
|
|
|
* |
347
|
|
|
* @return void |
348
|
|
|
*/ |
349
|
1 |
|
public function deleteWhere($where, $value) |
350
|
|
|
{ |
351
|
1 |
|
$this->checkDb(); |
352
|
1 |
|
$values = is_array($value) ? $value : [$value]; |
353
|
|
|
|
354
|
1 |
|
$this->db->connect() |
355
|
1 |
|
->deleteFrom($this->tableName) |
356
|
1 |
|
->where($where) |
357
|
1 |
|
->execute($values); |
358
|
1 |
|
} |
359
|
|
|
} |
360
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.