Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like AbstractDbEntity often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AbstractDbEntity, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | abstract class AbstractDbEntity implements \Serializable |
||
23 | { |
||
24 | /** |
||
25 | * The database table name (meant to be overridden). |
||
26 | * |
||
27 | * @var string |
||
28 | */ |
||
29 | protected static $dbTableName; |
||
30 | |||
31 | /** |
||
32 | * Entity's database properties and their attributes (meant to be overridden). |
||
33 | * Example format: |
||
34 | * |
||
35 | * $dbProperties = [ |
||
36 | * 'productId' => ['type' => 'int'], |
||
37 | * 'otherId' => ['type' => 'int', 'required' => true, 'validate' => false], |
||
38 | * 'name' => ['type' => 'string', 'maxLength' => 10, 'required' => true, 'default' => 'Some name'], |
||
39 | * ]; |
||
40 | * |
||
41 | * 'type' => 'int' Corresponding PHP type (required). |
||
42 | * 'validate' => false Turn off data validation, for example on required key fields that are set internally. |
||
43 | * 'required' => true The value have to be set (not '', null, false) |
||
44 | * 'nonEmpty' => true The value should not be empty ('', 0, null) |
||
45 | * |
||
46 | * Properties correspond to database table's columns but words are |
||
47 | * camel cased instead of separated with underscore (_) as in the database. |
||
48 | * |
||
49 | * @var array |
||
50 | */ |
||
51 | protected static $dbProperties = []; |
||
52 | |||
53 | /** |
||
54 | * Object database field name that is used for primary key (meant to be overridden). |
||
55 | * Should be camel cased as it maps to the dbFields array. |
||
56 | * |
||
57 | * @var string|array |
||
58 | */ |
||
59 | protected static $primaryDbPropertyKey; |
||
60 | |||
61 | /** |
||
62 | * @var array |
||
63 | */ |
||
64 | private static $cachedDefaultDbData = []; |
||
65 | |||
66 | /** |
||
67 | * @var array |
||
68 | */ |
||
69 | private static $cachedDbPropertyNames; |
||
70 | |||
71 | /** |
||
72 | * @var array |
||
73 | */ |
||
74 | private static $cachedDbFieldNames; |
||
75 | |||
76 | /** |
||
77 | * @var array |
||
78 | */ |
||
79 | private static $typeDefaults = [ |
||
80 | 'string' => '', |
||
81 | 'int' => 0, |
||
82 | 'float' => 0.0, |
||
83 | 'bool' => false, |
||
84 | ]; |
||
85 | |||
86 | /** |
||
87 | * Database row data with field names and their values. |
||
88 | * |
||
89 | * @var array |
||
90 | */ |
||
91 | private $dbData = []; |
||
92 | |||
93 | /** |
||
94 | * Database fields that has had their value modified since init/load. |
||
95 | * |
||
96 | * @var array |
||
97 | */ |
||
98 | private $modifiedDbProperties = []; |
||
99 | |||
100 | /** |
||
101 | * @var bool |
||
102 | */ |
||
103 | private $deleteFromDbOnSave = false; |
||
104 | |||
105 | /** |
||
106 | * @var bool |
||
107 | */ |
||
108 | private $deleted = false; |
||
109 | |||
110 | /** |
||
111 | * @var bool |
||
112 | */ |
||
113 | private $forceDbInsertOnSave = false; |
||
114 | |||
115 | /** |
||
116 | * Constructor. |
||
117 | * |
||
118 | * @param mixed $primaryDbValueOrRowData |
||
119 | */ |
||
120 | 64 | public function __construct($primaryDbValueOrRowData = null) |
|
121 | { |
||
122 | 64 | self::checkStaticProperties(); |
|
123 | |||
124 | // Set default values |
||
125 | 63 | $this->dbData = $this->getDefaultDbData(); |
|
126 | |||
127 | // Override default values with provided values |
||
128 | 63 | if ($primaryDbValueOrRowData !== null) { |
|
129 | 13 | $this->setPrimaryDbValueOrRowData($primaryDbValueOrRowData); |
|
130 | } |
||
131 | 63 | } |
|
132 | |||
133 | /** |
||
134 | * Make sure that class has all necessary static properties set. |
||
135 | */ |
||
136 | 64 | private static function checkStaticProperties() |
|
137 | { |
||
138 | 64 | static $checkedClasses = []; |
|
139 | 64 | if (!in_array(static::class, $checkedClasses)) { |
|
140 | 7 | if (!static::$dbTableName |
|
141 | 6 | || !static::$dbProperties |
|
|
|||
142 | 6 | || !static::$primaryDbPropertyKey |
|
143 | 6 | || (is_scalar(static::$primaryDbPropertyKey) |
|
144 | 6 | && !isset(static::$dbProperties[static::$primaryDbPropertyKey]['type'])) |
|
145 | 6 | || (is_array(static::$primaryDbPropertyKey) |
|
146 | 7 | && !Arr::allIn(static::$primaryDbPropertyKey, array_keys(static::$dbProperties))) |
|
147 | ) { |
||
148 | 1 | throw new \LogicException("All db entity's static properties not set"); |
|
149 | } |
||
150 | 6 | $checkedClasses[] = static::class; |
|
151 | } |
||
152 | 63 | } |
|
153 | |||
154 | /** |
||
155 | * @param mixed $primaryDbValueOrRowData |
||
156 | */ |
||
157 | 13 | public function setPrimaryDbValueOrRowData($primaryDbValueOrRowData = null) |
|
158 | { |
||
159 | // Row data would ba an associative array (not sequential, that would indicate a multi column primary key) |
||
160 | 13 | if (is_array($primaryDbValueOrRowData) && !isset($primaryDbValueOrRowData[0])) { |
|
161 | 1 | $this->setDbDataFromRow($primaryDbValueOrRowData); |
|
162 | } else { |
||
163 | 12 | $this->setPrimaryDbValue($primaryDbValueOrRowData); |
|
164 | } |
||
165 | 13 | } |
|
166 | |||
167 | /** |
||
168 | * Get all default database values. |
||
169 | * |
||
170 | * @return array |
||
171 | */ |
||
172 | 63 | public function getDefaultDbData() |
|
173 | { |
||
174 | 63 | $class = get_called_class(); |
|
175 | 63 | if (!isset(self::$cachedDefaultDbData[$class])) { |
|
176 | 6 | self::$cachedDefaultDbData[$class] = []; |
|
177 | 6 | foreach (array_keys(static::$dbProperties) as $propertyName) { |
|
178 | 6 | self::$cachedDefaultDbData[$class][$propertyName] = $this->getDefaultDbPropertyValue($propertyName); |
|
179 | } |
||
180 | } |
||
181 | |||
182 | 63 | return self::$cachedDefaultDbData[$class]; |
|
183 | } |
||
184 | |||
185 | /** |
||
186 | * Get default db value (can be overridden if non static default values need to be used). |
||
187 | * |
||
188 | * @param string $propertyName |
||
189 | * @return mixed |
||
190 | */ |
||
191 | 6 | public function getDefaultDbPropertyValue($propertyName) |
|
192 | { |
||
193 | // A default value is set |
||
194 | 6 | if (array_key_exists('default', static::$dbProperties[$propertyName])) { |
|
195 | 4 | $defaultValue = static::$dbProperties[$propertyName]['default']; |
|
196 | // No default value set, use default for type |
||
197 | } else { |
||
198 | 6 | $defaultValue = self::$typeDefaults[static::$dbProperties[$propertyName]['type']]; |
|
199 | } |
||
200 | |||
201 | 6 | return $defaultValue; |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * @return mixed |
||
206 | */ |
||
207 | 21 | public function getPrimaryDbValue() |
|
208 | { |
||
209 | 21 | if (is_array(static::$primaryDbPropertyKey)) { |
|
210 | 3 | $primaryValues = []; |
|
211 | 3 | foreach (static::$primaryDbPropertyKey as $keyPart) { |
|
212 | 3 | $primaryValues[] = $this->dbData[$keyPart]; |
|
213 | } |
||
214 | |||
215 | 3 | return $primaryValues; |
|
216 | } |
||
217 | |||
218 | 18 | return $this->dbData[static::$primaryDbPropertyKey]; |
|
219 | } |
||
220 | |||
221 | /** |
||
222 | * @param mixed $primaryDbValue |
||
223 | */ |
||
224 | 17 | public function setPrimaryDbValue($primaryDbValue) |
|
225 | { |
||
226 | 17 | if (is_array(static::$primaryDbPropertyKey)) { |
|
227 | 3 | if (!is_array($primaryDbValue)) { |
|
228 | 1 | throw new \InvalidArgumentException("Primary db value should be an array"); |
|
229 | } |
||
230 | |||
231 | 2 | reset($primaryDbValue); |
|
232 | 2 | foreach (static::$primaryDbPropertyKey as $keyPart) { |
|
233 | 2 | $this->dbData[$keyPart] = current($primaryDbValue); |
|
234 | 2 | next($primaryDbValue); |
|
235 | } |
||
236 | } else { |
||
237 | 14 | $this->dbData[static::$primaryDbPropertyKey] = $primaryDbValue; |
|
238 | } |
||
239 | 16 | } |
|
240 | |||
241 | /** |
||
242 | * @return bool |
||
243 | */ |
||
244 | 9 | public function isNewDbEntity() |
|
255 | |||
256 | /** |
||
257 | * @return bool |
||
258 | */ |
||
259 | 8 | public function shouldInsertOnDbSave() |
|
264 | |||
265 | /** |
||
266 | * Set a row field value. |
||
267 | * |
||
268 | * @param string $property |
||
269 | * @param mixed $value |
||
270 | * @param bool $setAsModified |
||
271 | */ |
||
272 | 23 | protected function setDbValue($property, $value, $setAsModified = true) |
|
273 | { |
||
274 | 23 | if (!isset(static::$dbProperties[$property])) { |
|
275 | 1 | throw new \InvalidArgumentException("No database entity property[{$property}] exists"); |
|
276 | } |
||
277 | |||
278 | // Don't set type if value is null and allowed (allowed currently indicated by default => null) |
||
279 | 22 | $nullIsAllowed = (array_key_exists('default', static::$dbProperties[$property]) |
|
280 | 22 | && static::$dbProperties[$property]['default'] === null); |
|
281 | 22 | if (!($value === null && $nullIsAllowed)) { |
|
282 | 22 | $type = static::$dbProperties[$property]['type']; |
|
283 | // Set null when empty and default is null |
||
284 | 22 | if ($value === '' && $nullIsAllowed) { |
|
285 | 1 | $value = null; |
|
286 | } else { |
||
287 | 22 | settype($value, $type); |
|
288 | } |
||
289 | } |
||
290 | |||
291 | 22 | $this->dbData[$property] = $value; |
|
292 | |||
293 | 22 | if ($setAsModified && !$this->isDbPropertyModified($property)) { |
|
294 | 15 | $this->modifiedDbProperties[] = $property; |
|
295 | } |
||
296 | 22 | } |
|
297 | |||
298 | /** |
||
299 | * Get a database field value. |
||
300 | * |
||
301 | * @param string $property |
||
302 | * @return mixed |
||
303 | */ |
||
304 | 8 | protected function getDbValue($property) |
|
308 | |||
309 | /** |
||
310 | * Get raw (with underscore as word separator as it is formatted in database) |
||
311 | * field name from a object field property name (camelcased). |
||
312 | * |
||
313 | * @param string $propertyName |
||
314 | * @return string |
||
315 | */ |
||
316 | 18 | public static function getDbFieldName($propertyName) |
|
317 | { |
||
318 | 18 | if (!isset(self::$cachedDbFieldNames[$propertyName])) { |
|
319 | 5 | self::$cachedDbFieldNames[$propertyName] = Str::camelToSeparator($propertyName); |
|
320 | } |
||
321 | |||
322 | 18 | return self::$cachedDbFieldNames[$propertyName]; |
|
323 | } |
||
324 | |||
325 | /** |
||
326 | * Get object field property name (camelCased) from database field name (underscore separated). |
||
327 | * |
||
328 | * @param string $dbFieldName |
||
329 | * @return string |
||
330 | */ |
||
331 | 7 | public static function getDbPropertyName($dbFieldName) |
|
332 | { |
||
333 | 7 | if (!isset(self::$cachedDbPropertyNames[$dbFieldName])) { |
|
334 | 2 | self::$cachedDbPropertyNames[$dbFieldName] = Str::separatorToCamel($dbFieldName); |
|
335 | } |
||
336 | |||
337 | 7 | return self::$cachedDbPropertyNames[$dbFieldName]; |
|
338 | } |
||
339 | |||
340 | /** |
||
341 | * @return bool |
||
342 | */ |
||
343 | 5 | public function hasModifiedDbProperties() |
|
344 | { |
||
345 | 5 | return !empty($this->modifiedDbProperties); |
|
346 | } |
||
347 | |||
348 | /** |
||
349 | * @param string $property |
||
350 | * @return bool |
||
351 | */ |
||
352 | 15 | public function isDbPropertyModified($property) |
|
353 | { |
||
354 | 15 | return in_array($property, $this->modifiedDbProperties); |
|
355 | } |
||
356 | |||
357 | /** |
||
358 | * @return array |
||
359 | */ |
||
360 | 5 | public function getModifiedDbData() |
|
364 | |||
365 | /** |
||
366 | * @param string $property |
||
367 | */ |
||
368 | public function clearModifiedDbProperty($property) |
||
369 | { |
||
370 | if (($key = array_search($property, $this->modifiedDbProperties))) { |
||
371 | unset($this->modifiedDbProperties[$key]); |
||
372 | } |
||
373 | } |
||
374 | |||
375 | /** |
||
376 | */ |
||
377 | 4 | public function clearModifiedDbProperties() |
|
381 | |||
382 | /** |
||
383 | * Magic method used to automate getters & setters for row data. |
||
384 | * |
||
385 | * @param string $name |
||
386 | * @param array $arguments |
||
387 | * @return mixed |
||
388 | */ |
||
389 | 17 | public function __call($name, array $arguments = []) |
|
406 | |||
407 | /** |
||
408 | * Set database fields' data. |
||
409 | * |
||
410 | * @param array $data |
||
411 | */ |
||
412 | 3 | public function setDbData(array $data) |
|
413 | { |
||
414 | 3 | View Code Duplication | foreach (array_keys(static::$dbProperties) as $propertyName) { |
415 | 3 | if (array_key_exists($propertyName, $data)) { |
|
416 | 3 | $this->setDbValue($propertyName, $data[$propertyName], true); |
|
417 | } |
||
418 | } |
||
419 | 3 | } |
|
420 | |||
421 | /** |
||
422 | * Set db data from raw database row data with field names in database format. |
||
423 | * |
||
424 | * @param array $rowData |
||
425 | */ |
||
426 | 7 | public function setDbDataFromRow(array $rowData) |
|
427 | { |
||
428 | // If there are less row data than properties, use rows as starting point (optimization) |
||
429 | 7 | if (count($rowData) < count(static::$dbProperties)) { |
|
430 | 6 | foreach ($rowData as $dbFieldName => $value) { |
|
431 | 6 | $propertyName = static::getDbPropertyName($dbFieldName); |
|
432 | 6 | if (isset(static::$dbProperties[$propertyName])) { |
|
433 | 6 | $this->setDbValue($propertyName, $value, false); |
|
434 | } |
||
435 | } |
||
436 | // If there are more row data than properties, use properties as starting point |
||
437 | } else { |
||
438 | 2 | View Code Duplication | foreach (array_keys(static::$dbProperties) as $propertyName) { |
439 | 2 | $fieldName = static::getDbFieldName($propertyName); |
|
440 | 2 | if (array_key_exists($fieldName, $rowData)) { |
|
441 | 2 | $this->setDbValue($propertyName, $rowData[$fieldName], false); |
|
442 | } |
||
443 | } |
||
444 | } |
||
445 | 7 | } |
|
446 | |||
447 | /** |
||
448 | * @return array |
||
449 | */ |
||
450 | 8 | public function getDbData() |
|
454 | |||
455 | /** |
||
456 | * @return array |
||
457 | */ |
||
458 | 2 | public function getDbDataWithoutPrimary() |
|
459 | { |
||
460 | 2 | $dbDataWithoutPrimary = $this->dbData; |
|
461 | |||
462 | 2 | if (is_array(static::$primaryDbPropertyKey)) { |
|
463 | 1 | foreach (static::$primaryDbPropertyKey as $keyPart) { |
|
464 | 1 | unset($dbDataWithoutPrimary[$keyPart]); |
|
465 | } |
||
466 | } else { |
||
467 | 1 | unset($dbDataWithoutPrimary[static::$primaryDbPropertyKey]); |
|
468 | } |
||
469 | |||
470 | 2 | return $dbDataWithoutPrimary; |
|
471 | } |
||
472 | |||
473 | /** |
||
474 | * @param bool $deleteFromDbOnSave |
||
475 | */ |
||
476 | 3 | public function setDeleteFromDbOnSave($deleteFromDbOnSave = true) |
|
480 | |||
481 | /** |
||
482 | * @return bool |
||
483 | */ |
||
484 | 10 | public function shouldBeDeletedFromDbOnSave() |
|
488 | |||
489 | /** |
||
490 | * @return bool; |
||
491 | */ |
||
492 | 1 | public function isDeleted() |
|
496 | |||
497 | /** |
||
498 | * @param bool $deleted |
||
499 | */ |
||
500 | 3 | public function setDeleted($deleted = true) |
|
504 | |||
505 | /** |
||
506 | * @param bool $forceDbInsertOnSave |
||
507 | */ |
||
508 | 5 | public function setForceDbInsertOnSave($forceDbInsertOnSave) |
|
512 | |||
513 | /** |
||
514 | * @return bool |
||
515 | */ |
||
516 | 9 | public function shouldForceDbInsertOnSave() |
|
520 | |||
521 | /** |
||
522 | * @param string $propertyName |
||
523 | * @return int|null |
||
524 | */ |
||
525 | 6 | public static function getDbPropertyMaxLength($propertyName) |
|
531 | |||
532 | /** |
||
533 | * @param string $propertyName |
||
534 | * @return bool |
||
535 | */ |
||
536 | 2 | public static function getDbPropertyRequired($propertyName) |
|
542 | |||
543 | /** |
||
544 | * @param string $propertyName |
||
545 | * @return bool |
||
546 | */ |
||
547 | 3 | public static function getDbPropertyNonEmpty($propertyName) |
|
553 | |||
554 | /** |
||
555 | * Get validator for object's database data. |
||
556 | * |
||
557 | * @param ValidatorTranslatorInterface|SymfonyTranslatorInterface|null $translator |
||
558 | * @return Validator |
||
559 | */ |
||
560 | 3 | public function getDbDataValidator($translator = null) |
|
561 | { |
||
562 | 3 | $validRuleProperties = Validator::getValidRuleProperties(); |
|
563 | 3 | $fieldsRuleProperties = []; |
|
564 | 3 | foreach (static::$dbProperties as $propertyName => $attributes) { |
|
565 | // Always validate if validate is not explicitly set to false |
||
566 | 3 | if (!isset($attributes['validate']) || $attributes['validate'] === true) { |
|
567 | 3 | $fieldsRuleProperties[$propertyName] = []; |
|
568 | 3 | foreach ($validRuleProperties as $ruleName) { |
|
569 | 3 | if (isset($attributes[$ruleName])) { |
|
570 | 3 | $fieldsRuleProperties[$propertyName][$ruleName] = $attributes[$ruleName]; |
|
571 | } |
||
572 | } |
||
573 | } |
||
574 | } |
||
575 | |||
576 | 3 | $validator = new Validator($fieldsRuleProperties, $translator); |
|
577 | |||
578 | 3 | return $validator; |
|
579 | } |
||
580 | |||
581 | /** |
||
582 | * Validate and (if no error messages) set database data. |
||
583 | * |
||
584 | * @param array $data The data (e.g. from a form post) to be validated and set |
||
585 | * @param ValidatorTranslatorInterface|SymfonyTranslatorInterface|null $translator |
||
586 | * @return array An array with all (if any) of error messages |
||
587 | */ |
||
588 | 2 | public function validateAndSetDbData(array $data, $translator = null) |
|
589 | { |
||
590 | // Get arguments this method was called with, to allow passthrough to getDbDataValidator() |
||
591 | 2 | $args = array_slice(func_get_args(), 1); |
|
592 | |||
593 | 2 | $validator = call_user_func_array([$this, 'getDbDataValidator'], $args); |
|
594 | 2 | $errorMessages = $validator->validate($data); |
|
595 | |||
596 | 2 | if (empty($errorMessages)) { |
|
597 | // Set db data from validated data because validator normalizes data as well (like trim) |
||
598 | 1 | $this->setDbData($validator->getValidatedData()); |
|
599 | } |
||
600 | |||
601 | 2 | return $errorMessages; |
|
602 | } |
||
603 | |||
604 | /** |
||
605 | * @return string|array |
||
606 | */ |
||
607 | 17 | public static function getPrimaryDbPropertyKey() |
|
611 | |||
612 | /** |
||
613 | * @return string|array |
||
614 | */ |
||
615 | 9 | public static function getPrimaryDbFieldKey() |
|
616 | { |
||
617 | 9 | $primaryDbPropertyKey = static::getPrimaryDbPropertyKey(); |
|
618 | |||
619 | 9 | if (is_array($primaryDbPropertyKey)) { |
|
620 | 2 | $primaryDbFieldKey = []; |
|
621 | 2 | foreach ($primaryDbPropertyKey as $propertyName) { |
|
622 | 2 | $primaryDbFieldKey[] = static::getDbFieldName($propertyName); |
|
623 | } |
||
624 | |||
625 | 2 | return $primaryDbFieldKey; |
|
626 | } else { |
||
627 | 7 | return static::getDbFieldName($primaryDbPropertyKey); |
|
628 | } |
||
629 | } |
||
630 | |||
631 | /** |
||
632 | * Return array with db property names. |
||
633 | * |
||
634 | * @param array $exclude |
||
635 | * @return array |
||
636 | */ |
||
637 | 1 | public static function getDbPropertyNames(array $exclude = []) |
|
643 | |||
644 | /** |
||
645 | * Return array with raw db field names. |
||
646 | * |
||
647 | * @param array $exclude |
||
648 | * @return array |
||
649 | */ |
||
650 | 3 | public static function getDbFieldNames(array $exclude = []) |
|
651 | { |
||
652 | 3 | $fieldNames = []; |
|
653 | 3 | foreach (array_keys(static::$dbProperties) as $propertyName) { |
|
654 | 3 | $fieldNames[] = static::getDbFieldName($propertyName); |
|
655 | } |
||
656 | |||
657 | 3 | return $exclude ? array_diff($fieldNames, $exclude) : $fieldNames; |
|
658 | } |
||
659 | |||
660 | |||
661 | /** |
||
662 | * Get raw database field names prefixed (id, name becomes t.id, t.name etc.). |
||
663 | * |
||
664 | * @param string $dbTableAlias |
||
665 | * @param array $exclude |
||
666 | * @return array |
||
667 | */ |
||
668 | 1 | public static function getPrefixedDbFieldNames($dbTableAlias, array $exclude = []) |
|
672 | |||
673 | /** |
||
674 | * Get database columns transformed from e.g. "productId, date" to "p.product_id AS p_product_id, p.date AS p_date". |
||
675 | * |
||
676 | * @param string $dbTableAlias |
||
677 | * @param array $exclude |
||
678 | * @return array |
||
679 | */ |
||
680 | 1 | public static function getAliasedDbFieldNames($dbTableAlias, array $exclude = []) |
|
681 | { |
||
682 | 1 | $newArray = []; |
|
683 | 1 | foreach (static::getDbFieldNames($exclude) as $dbFieldName) { |
|
684 | 1 | $fromCol = $dbTableAlias . '.' . $dbFieldName; |
|
685 | 1 | $toCol = $dbTableAlias . '_' . $dbFieldName; |
|
686 | 1 | $newArray[] = $fromCol . ' AS ' . $toCol; |
|
687 | } |
||
688 | |||
689 | 1 | return $newArray; |
|
690 | } |
||
691 | |||
692 | /** |
||
693 | * Filters a full db item array by it's table alias and the strips the table alias. |
||
694 | * |
||
695 | * @param array $rowData |
||
696 | * @param string $dbTableAlias |
||
697 | * @param bool $skipStrip For cases when you want to filter only (no stripping) |
||
698 | * @return array |
||
699 | */ |
||
700 | 1 | public static function filterStripDbRowData(array $rowData, $dbTableAlias, $skipStrip = false) |
|
701 | { |
||
702 | 1 | $columnPrefix = $dbTableAlias . '_'; |
|
703 | |||
704 | 1 | $filteredAndStrippedRowData = []; |
|
705 | 1 | foreach ($rowData as $key => $val) { |
|
706 | 1 | if (strpos($key, $columnPrefix) === 0) { |
|
707 | 1 | $strippedKey = $skipStrip ? $key : Str::stripLeft($key, $columnPrefix); |
|
708 | 1 | $filteredAndStrippedRowData[$strippedKey] = $val; |
|
709 | } |
||
710 | } |
||
711 | |||
712 | 1 | return $filteredAndStrippedRowData; |
|
713 | } |
||
714 | |||
715 | /** |
||
716 | * @return string |
||
717 | */ |
||
718 | 8 | public static function getDbTableName() |
|
722 | |||
723 | /** |
||
724 | * Method to handle the serialization of this object. |
||
725 | * |
||
726 | * Implementation of Serializable interface. If descendant private properties |
||
727 | * should be serialized, they need to be visible to this parent (i.e. not private). |
||
728 | * |
||
729 | * @return string |
||
730 | */ |
||
731 | 2 | public function serialize() |
|
735 | |||
736 | /** |
||
737 | * Method to handle the unserialization of this object. |
||
738 | * |
||
739 | * Implementation of Serializable interface. If descendant private properties |
||
740 | * should be unserialized, they need to be visible to this parent (i.e. not private). |
||
741 | * |
||
742 | * @param string $serializedObject |
||
743 | */ |
||
744 | 1 | public function unserialize($serializedObject) |
|
745 | { |
||
746 | 1 | $objectVars = unserialize($serializedObject); |
|
747 | |||
748 | 1 | foreach ($objectVars as $key => $value) { |
|
749 | 1 | $this->{$key} = $value; |
|
750 | } |
||
751 | 1 | } |
|
752 | |||
753 | /** |
||
754 | * Merges other object's modified database data into this object. |
||
755 | * |
||
756 | * @param AbstractDbEntity $otherEntity |
||
757 | */ |
||
758 | 1 | public function mergeWith(AbstractDbEntity $otherEntity) |
|
763 | } |
||
764 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.