1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the miBadger package. |
5
|
|
|
* |
6
|
|
|
* @author Michael Webbers <[email protected]> |
7
|
|
|
* @license http://opensource.org/licenses/Apache-2.0 Apache v2 License |
8
|
|
|
* @version 1.0.0 |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace miBadger\ActiveRecord; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* The abstract active record class. |
15
|
|
|
* |
16
|
|
|
* @since 1.0.0 |
17
|
|
|
*/ |
18
|
|
|
abstract class AbstractActiveRecord implements ActiveRecordInterface |
19
|
|
|
{ |
20
|
|
|
/** @var \PDO The PDO object. */ |
21
|
|
|
private $pdo; |
22
|
|
|
|
23
|
|
|
/** @var null|int The ID. */ |
24
|
|
|
private $id; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Construct an abstract pdo active record with the given pdo. |
28
|
|
|
* |
29
|
|
|
* @param \PDO $pdo |
30
|
|
|
*/ |
31
|
21 |
|
public function __construct(\PDO $pdo) |
32
|
|
|
{ |
33
|
21 |
|
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC); |
34
|
21 |
|
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); |
35
|
|
|
|
36
|
21 |
|
$this->setPdo($pdo); |
37
|
21 |
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* {@inheritdoc} |
41
|
|
|
*/ |
42
|
3 |
|
public function create() |
43
|
|
|
{ |
44
|
|
|
try { |
45
|
3 |
|
$pdoStatement = $this->getPdo()->prepare($this->getCreateQuery()); |
46
|
1 |
|
$pdoStatement->execute($this->getActiveRecordData()); |
47
|
|
|
|
48
|
1 |
|
$this->setId(intval($this->getPdo()->lastInsertId())); |
49
|
3 |
|
} catch(\PDOException $e) { |
50
|
2 |
|
throw new ActiveRecordException('Can\'t create the record.', 0, $e); |
51
|
|
|
} |
52
|
|
|
|
53
|
1 |
|
return $this; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Returns the create query. |
58
|
|
|
* |
59
|
|
|
* @return string the create query. |
60
|
|
|
*/ |
61
|
3 |
View Code Duplication |
private function getCreateQuery() |
|
|
|
|
62
|
|
|
{ |
63
|
3 |
|
$columns = array_keys($this->getActiveRecordData()); |
64
|
3 |
|
$values = []; |
65
|
|
|
|
66
|
3 |
|
foreach ($columns as $key => $value) { |
67
|
3 |
|
$values[] = ':' . $value; |
68
|
3 |
|
} |
69
|
|
|
|
70
|
3 |
|
return sprintf('INSERT INTO %s (%s) VALUES (%s)', $this->getActiveRecordName(), implode(', ', $columns), implode(', ', $values)); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* {@inheritdoc} |
75
|
|
|
*/ |
76
|
6 |
|
public function read($id) |
77
|
|
|
{ |
78
|
|
|
try { |
79
|
6 |
|
$pdoStatement = $this->getPdo()->prepare($this->getReadQuery()); |
80
|
5 |
|
$pdoStatement->execute(['id' => $id]); |
81
|
|
|
|
82
|
5 |
|
$this->setActiveRecordData($pdoStatement->fetch()); |
83
|
4 |
|
$this->setId($id); |
84
|
6 |
|
} catch (\PDOException $e) { |
85
|
1 |
|
throw new ActiveRecordException('Can\'t read the record.', 0, $e); |
86
|
|
|
} |
87
|
|
|
|
88
|
4 |
|
return $this; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Returns the read query. |
93
|
|
|
* |
94
|
|
|
* @return string the read query. |
95
|
|
|
*/ |
96
|
6 |
|
private function getReadQuery() |
97
|
|
|
{ |
98
|
6 |
|
return sprintf('SELECT * FROM `%s` WHERE `id` = :id', $this->getActiveRecordName()); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* {@inheritdoc} |
103
|
|
|
*/ |
104
|
4 |
View Code Duplication |
public function update() |
|
|
|
|
105
|
|
|
{ |
106
|
4 |
|
if (!$this->exists()) { |
107
|
1 |
|
throw new ActiveRecordException('Can\'t update a non-existent record.'); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
try { |
111
|
3 |
|
$pdoStatement = $this->getPdo()->prepare($this->getUpdateQuery()); |
112
|
1 |
|
$pdoStatement->execute(['id' => $this->getId()] + $this->getActiveRecordData()); |
113
|
3 |
|
} catch (\PDOException $e) { |
114
|
2 |
|
throw new ActiveRecordException('Can\'t update the record.', 0, $e); |
115
|
|
|
} |
116
|
|
|
|
117
|
1 |
|
return $this; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Returns the update query. |
122
|
|
|
* |
123
|
|
|
* @return string the update query. |
124
|
|
|
*/ |
125
|
3 |
View Code Duplication |
private function getUpdateQuery() |
|
|
|
|
126
|
|
|
{ |
127
|
3 |
|
$values = []; |
128
|
|
|
|
129
|
3 |
|
foreach (array_keys($this->getActiveRecordData()) as $key => $value) { |
130
|
3 |
|
$values[] = $value . ' = :' . $value; |
131
|
3 |
|
} |
132
|
|
|
|
133
|
3 |
|
return sprintf('UPDATE %s SET %s WHERE `id` = :id', $this->getActiveRecordName(), implode(', ', $values)); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* {@inheritdoc} |
138
|
|
|
*/ |
139
|
3 |
View Code Duplication |
public function delete() |
|
|
|
|
140
|
|
|
{ |
141
|
3 |
|
if (!$this->exists()) { |
142
|
1 |
|
throw new ActiveRecordException('Can\'t delete a non-existent record.'); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
try { |
146
|
2 |
|
$pdoStatement = $this->getPdo()->prepare($this->getDeleteQuery()); |
147
|
1 |
|
$pdoStatement->execute(['id' => $this->getId()]); |
148
|
|
|
|
149
|
1 |
|
$this->setId(null); |
150
|
2 |
|
} catch (\PDOException $e) { |
151
|
1 |
|
throw new ActiveRecordException('Can\'t delete the record.', 0, $e); |
152
|
|
|
} |
153
|
|
|
|
154
|
1 |
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Returns the delete query. |
159
|
|
|
* |
160
|
|
|
* @return string the delete query. |
161
|
|
|
*/ |
162
|
2 |
|
private function getDeleteQuery() |
163
|
|
|
{ |
164
|
2 |
|
return sprintf('DELETE FROM %s WHERE `id` = :id', $this->getActiveRecordName()); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* {@inheritdoc} |
169
|
|
|
*/ |
170
|
8 |
|
public function exists() |
171
|
|
|
{ |
172
|
8 |
|
return $this->getId() !== null; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Returns the PDO. |
177
|
|
|
* |
178
|
|
|
* @return \PDO the PDO. |
179
|
|
|
*/ |
180
|
19 |
|
public function getPdo() |
181
|
|
|
{ |
182
|
19 |
|
return $this->pdo; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Set the PDO. |
187
|
|
|
* |
188
|
|
|
* @param \PDO $pdo |
189
|
|
|
* @return $this |
190
|
|
|
*/ |
191
|
21 |
|
protected function setPdo($pdo) |
192
|
|
|
{ |
193
|
21 |
|
$this->pdo = $pdo; |
194
|
|
|
|
195
|
21 |
|
return $this; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Returns the ID. |
200
|
|
|
* |
201
|
|
|
* @return null|int The ID. |
202
|
|
|
*/ |
203
|
6 |
|
public function getId() |
204
|
|
|
{ |
205
|
6 |
|
return $this->id; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Set the ID. |
210
|
|
|
* |
211
|
|
|
* @param int $id |
212
|
|
|
* @return $this |
213
|
|
|
*/ |
214
|
8 |
|
protected function setId($id) |
215
|
|
|
{ |
216
|
8 |
|
$this->id = $id; |
217
|
|
|
|
218
|
8 |
|
return $this; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* Returns the active record name. |
223
|
|
|
* |
224
|
|
|
* @return string the active record name. |
225
|
|
|
*/ |
226
|
|
|
abstract protected function getActiveRecordName(); |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Returns the active record data. |
230
|
|
|
* |
231
|
|
|
* @return array the active record data. |
232
|
|
|
*/ |
233
|
|
|
abstract protected function getActiveRecordData(); |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* Set the active record data. |
237
|
|
|
* |
238
|
|
|
* @param array $fetch |
239
|
|
|
* @return null |
240
|
|
|
*/ |
241
|
8 |
|
protected function setActiveRecordData(array $fetch) |
242
|
|
|
{ |
243
|
8 |
|
$data = $this->getActiveRecordData(); |
244
|
|
|
|
245
|
8 |
|
foreach ($data as $key => &$value) { |
246
|
8 |
|
if (!isset($fetch[$key])) { |
247
|
1 |
|
throw new ActiveRecordException(sprintf('Can\'t read the expected column "%s". It\'s not returnd by the database', $key)); |
248
|
|
|
} |
249
|
|
|
|
250
|
8 |
|
$value = $fetch[$key]; |
251
|
8 |
|
} |
252
|
7 |
|
} |
253
|
|
|
} |
254
|
|
|
|
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.