1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Rentgen\Database\Constraint; |
4
|
|
|
|
5
|
|
|
use Rentgen\Database\Table; |
6
|
|
|
|
7
|
|
|
class ForeignKey implements ConstraintInterface |
8
|
|
|
{ |
9
|
|
|
|
10
|
|
|
const ACTION_NO_ACTION = 'NO ACTION'; |
11
|
|
|
const ACTION_CASCADE = 'CASCADE'; |
12
|
|
|
const ACTION_RESTICT = 'RESTRICT'; |
13
|
|
|
const ACTION_DEFAULT = 'SET DEFAULT'; |
14
|
|
|
const ACTION_SET_NULL = 'SET NULL'; |
15
|
|
|
|
16
|
|
|
private $columns; |
17
|
|
|
private $table; |
18
|
|
|
private $referencedTable; |
19
|
|
|
private $updateAction; |
20
|
|
|
private $deleteAction; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Constructor. |
24
|
|
|
* |
25
|
|
|
* @param Table $table Table instance. |
26
|
|
|
* @param Table $referencedTable Table reference instance. |
27
|
|
|
*/ |
28
|
|
|
public function __construct(Table $table, Table $referencedTable) |
29
|
|
|
{ |
30
|
|
|
$this->table = $table; |
31
|
|
|
$this->referencedTable = $referencedTable; |
32
|
|
|
|
33
|
|
|
$this->updateAction = $this->deleteAction = self::ACTION_NO_ACTION; |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* {@inheritdoc} |
38
|
|
|
*/ |
39
|
|
|
public function getName() |
40
|
|
|
{ |
41
|
|
|
$tableName = $this->table->getName(); |
42
|
|
|
$columnsAsString = implode('_', $this->columns); |
43
|
|
|
|
44
|
|
|
return $tableName . '_' . $columnsAsString . '_fkey'; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* {@inheritdoc} |
49
|
|
|
*/ |
50
|
|
|
public function getTable() |
51
|
|
|
{ |
52
|
|
|
return $this->table; |
|
|
|
|
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Sets a table instance. |
57
|
|
|
* |
58
|
|
|
* @param Table $table Table instance. |
59
|
|
|
* |
60
|
|
|
* @return PrimaryKey Self. |
61
|
|
|
*/ |
62
|
|
|
public function setTable(Table $table) |
63
|
|
|
{ |
64
|
|
|
$this->table = $table; |
65
|
|
|
|
66
|
|
|
return $this; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Gets a reference table name. |
71
|
|
|
* |
72
|
|
|
* @return string Reference table name. |
73
|
|
|
*/ |
74
|
|
|
public function getReferencedTable() |
75
|
|
|
{ |
76
|
|
|
return $this->referencedTable; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Sets foreign key columns. |
81
|
|
|
* |
82
|
|
|
* @param array $columns Columns list. |
83
|
|
|
* |
84
|
|
|
* @return ForeignKey Self instance. |
85
|
|
|
*/ |
86
|
|
View Code Duplication |
public function setColumns($columns) |
|
|
|
|
87
|
|
|
{ |
88
|
|
|
if (!is_array($columns)) { |
89
|
|
|
$columns = array($columns); |
90
|
|
|
} |
91
|
|
|
$this->columns = $columns; |
92
|
|
|
|
93
|
|
|
return $this; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Gets column names. |
98
|
|
|
* |
99
|
|
|
* @return array Column names. |
100
|
|
|
*/ |
101
|
|
|
public function getColumns() |
102
|
|
|
{ |
103
|
|
|
return $this->columns; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Sets foreign key reference columns. |
108
|
|
|
* |
109
|
|
|
* @param array $columns Columns list. |
110
|
|
|
* |
111
|
|
|
* @return ForeignKey Self instance. |
112
|
|
|
*/ |
113
|
|
View Code Duplication |
public function setReferencedColumns($columns) |
|
|
|
|
114
|
|
|
{ |
115
|
|
|
if (!is_array($columns)) { |
116
|
|
|
$columns = array($columns); |
117
|
|
|
} |
118
|
|
|
$this->referencedColumns = $columns; |
|
|
|
|
119
|
|
|
|
120
|
|
|
return $this; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Gets reference column names. |
125
|
|
|
* |
126
|
|
|
* @return array Column names. |
127
|
|
|
*/ |
128
|
|
|
public function getReferencedColumns() |
129
|
|
|
{ |
130
|
|
|
return $this->referencedColumns; |
|
|
|
|
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Gets an update action. |
135
|
|
|
* |
136
|
|
|
* @return string |
137
|
|
|
*/ |
138
|
|
|
public function getUpdateAction() |
139
|
|
|
{ |
140
|
|
|
return $this->updateAction; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Gets a delete action. |
145
|
|
|
* |
146
|
|
|
* @return string |
147
|
|
|
*/ |
148
|
|
|
public function getDeleteAction() |
149
|
|
|
{ |
150
|
|
|
return $this->deleteAction; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Sets an update action. |
155
|
|
|
* |
156
|
|
|
* @param string $updateAction Update action. |
157
|
|
|
* |
158
|
|
|
* @throws InvalidArgumentException If the provided argument is not of action type. |
159
|
|
|
* |
160
|
|
|
* @return void |
161
|
|
|
*/ |
162
|
|
View Code Duplication |
public function setUpdateAction($updateAction) |
|
|
|
|
163
|
|
|
{ |
164
|
|
|
$updateAction = strtoupper($updateAction); |
165
|
|
|
if (!in_array($updateAction, $this->getAvailableActions())) { |
166
|
|
|
throw new \InvalidArgumentException(sprintf('Action %s does not exist.', $updateAction)); |
167
|
|
|
} |
168
|
|
|
$this->updateAction = $updateAction; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Sets a delete action. |
173
|
|
|
* |
174
|
|
|
* @param string $deleteAction Delete action. |
175
|
|
|
* |
176
|
|
|
* @throws InvalidArgumentException If the provided argument is not of action type. |
177
|
|
|
* |
178
|
|
|
* @return void |
179
|
|
|
*/ |
180
|
|
View Code Duplication |
public function setDeleteAction($deleteAction) |
|
|
|
|
181
|
|
|
{ |
182
|
|
|
$deleteAction = strtoupper($deleteAction); |
183
|
|
|
if (!in_array($deleteAction, $this->getAvailableActions())) { |
184
|
|
|
throw new \InvalidArgumentException(sprintf('Action %s does not exist.', $deleteAction)); |
185
|
|
|
} |
186
|
|
|
$this->deleteAction = $deleteAction; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Sets an update action on restrict. |
191
|
|
|
* |
192
|
|
|
* @return ForeignKey |
193
|
|
|
*/ |
194
|
|
|
public function updateRestrict() |
195
|
|
|
{ |
196
|
|
|
$this->updateAction = self::ACTION_RESTICT; |
197
|
|
|
|
198
|
|
|
return $this; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Sets an update action on cascade. |
203
|
|
|
* |
204
|
|
|
* @return ForeignKey |
205
|
|
|
*/ |
206
|
|
|
public function updateCascade() |
207
|
|
|
{ |
208
|
|
|
$this->updateAction = self::ACTION_CASCADE; |
209
|
|
|
|
210
|
|
|
return $this; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Sets an update action on set null. |
215
|
|
|
* |
216
|
|
|
* @return ForeignKey |
217
|
|
|
*/ |
218
|
|
|
public function updateSetNull() |
219
|
|
|
{ |
220
|
|
|
$this->updateAction = self::ACTION_SET_NULL; |
221
|
|
|
|
222
|
|
|
return $this; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Sets an update action on default. |
227
|
|
|
* |
228
|
|
|
* @return ForeignKey |
229
|
|
|
*/ |
230
|
|
|
public function updateSetDefault() |
231
|
|
|
{ |
232
|
|
|
$this->updateAction = self::ACTION_DEFAULT; |
233
|
|
|
|
234
|
|
|
return $this; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Sets a delete action on restrict. |
239
|
|
|
* |
240
|
|
|
* @return ForeignKey |
241
|
|
|
*/ |
242
|
|
|
public function deleteRestrict() |
243
|
|
|
{ |
244
|
|
|
$this->deleteAction = self::ACTION_RESTICT; |
245
|
|
|
|
246
|
|
|
return $this; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Sets a delete action on cascade. |
251
|
|
|
* |
252
|
|
|
* @return ForeignKey |
253
|
|
|
*/ |
254
|
|
|
public function deleteCascade() |
255
|
|
|
{ |
256
|
|
|
$this->deleteAction = self::ACTION_CASCADE; |
257
|
|
|
|
258
|
|
|
return $this; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Sets a delete action on set null. |
263
|
|
|
* |
264
|
|
|
* @return ForeignKey |
265
|
|
|
*/ |
266
|
|
|
public function deleteSetNull() |
267
|
|
|
{ |
268
|
|
|
$this->deleteAction = self::ACTION_SET_NULL; |
269
|
|
|
|
270
|
|
|
return $this; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Sets a delete action on default. |
275
|
|
|
* |
276
|
|
|
* @return ForeignKey |
277
|
|
|
*/ |
278
|
|
|
public function deleteSetDefault() |
279
|
|
|
{ |
280
|
|
|
$this->deleteAction = self::ACTION_DEFAULT; |
281
|
|
|
|
282
|
|
|
return $this; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
private function getAvailableActions() |
286
|
|
|
{ |
287
|
|
|
return array( |
288
|
|
|
ForeignKey::ACTION_NO_ACTION, |
289
|
|
|
ForeignKey::ACTION_CASCADE, |
290
|
|
|
ForeignKey::ACTION_RESTICT, |
291
|
|
|
ForeignKey::ACTION_DEFAULT, |
292
|
|
|
ForeignKey::ACTION_SET_NULL |
293
|
|
|
); |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.