public function save() { $mapping = Reader::getMappedAttributeData(get_called_class()); $fieldDef = []; $fieldVals = []; foreach ($mapping as $propName => $propData) { if ($propName !== 'id') { $fieldDef[] = $propName; $getter = $propData['getter']; $fieldVals[] = Tool::getSqlValue($this->{$getter}(), $propData['datatype']); } } if (!$this->getId()) { $rq = 'INSERT INTO ' . Tool::camelCaseToSnakeCase($this->className) . ' (' . implode(',', $fieldDef) . ') VALUES (' . implode(',', array_fill(0, count($fieldDef), '?')) . ')'; $q = new Query($rq); $res = $q->execute($fieldVals); $this->setId($q->lastInsertedId()); return $res; } else { $rq = 'UPDATE ' . Tool::camelCaseToSnakeCase($this->className) . ' SET '; $modifiers = []; foreach ($fieldDef as $field) { $modifiers[] = "{$field} = ?"; } $rq .= implode(', ', $modifiers) . ' WHERE id = ' . $this->getId(); $q = new Query($rq); $res = $q->execute($fieldVals); return $res; } }
/** * Get database mapping for provided class */ public static function getMappedAttributeData($class) { $mapping = []; $reflectedClass = new \ReflectionClass($class); foreach ($reflectedClass->getProperties() as $prop) { $propName = $prop->getName(); // Look for annoration Type:<datatype> preg_match("#@Type:(.*?)\n#", $prop->getDocComment(), $typeAnnotation); if (isset($typeAnnotation[1])) { $type = trim($typeAnnotation[1]); $mapping[$propName] = ['datatype' => $type, 'setter' => Tool::getAccessor('set', $propName), 'getter' => Tool::getAccessor('get', $propName)]; } } return $mapping; }
public static function hydrate($data, $class) { // Retrieve mapping config for class $mapping = Reader::getMappedAttributeData($class); $object = new $class(); foreach ($data as $propName => $propValue) { if (isset($mapping[$propName])) { $convertedValue = Tool::convertValue($propValue, $mapping[$propName]['datatype']); $setter = $mapping[$propName]['setter']; try { $object->{$setter}($convertedValue); } catch (\Exception $e) { error_log('Hydratation error: ' . $e->getMessage()); } } } return $object; }