Skip to content

Instantly share code, notes, and snippets.

@beberlei
Created March 11, 2020 16:49
Show Gist options
  • Save beberlei/d9fac02e7309e692b0467ae89cda9e64 to your computer and use it in GitHub Desktop.
Save beberlei/d9fac02e7309e692b0467ae89cda9e64 to your computer and use it in GitHub Desktop.
<?php
class DatabaseMapper
{
public function map(array $row, string $class)
{
// these lines until the foreach ($row) loop only need to be done once per class
$reflection = new ReflectionClass($class);
$properties = [];
$columnPrefixes = [];
$associationClasses = [];
foreach ($reflection->getProperties() as $property) {
$properties[strtolower($property->getName())] = $property;
$association = $property->getAttributes(AssocationColumnPrefix::class);
if (count($association) > 0) {
$assocationAttribute = $association[0]->getAsObject();
$columnPrefixes[$property->getName()] = $assocationAttribute->prefix;
$associationClasses[$property->getName()] = $associationClasses->class;
}
}
// this needs to be done per row
$object = $reflection->newInstance();
$associationColumns = [];
foreach ($row as $column => $value) {
$property = str_replace("_", "", $column);
if (!isset($properties[$property])) {
continue;
}
if (!isset($columnPrefixes[$property])) {
// no column prefix? We assume its a regular field
$reflection->getMethod("set" . $property)->invoke($object, $value);
} else {
// we check if it matches a column prefix and store it for each
// assocation
foreach ($columnPrefixes as $associationProperty => $columnPrefix) {
if (strpos($column, $columnPrefix) === 0) {
// column prefix matched, such as "category_"
$associationColumn = str_replace($columnPrefix, "", $column);
$associationColumns[$associationProperty][$associationColumn] = $value;
break 2;
}
}
}
}
// now iterate all the associations we found, map and assign them
foreach ($associationColumns as $associationProperty => $row) {
$relatedObject = $this->map($row, $associationClasses[$associationProperty]);
$reflection->getMethod("set" . $associationProperty)->invoke($object, $relatedObject);
}
return $object;
}
}
class AssocationColumnPrefix implements \Php\Attribute
{
public $prefix;
public $class;
public function __construct(string $prefix, string $class) {
$this->prefix = $prefix;
$this->class = $class;
}
}
class Post
{
private $id;
private $name;
private $slug;
private $content;
<<AssocationColumnPrefix("category_", Category::class)>>
private $category;
}
$sql = 'SELECT p.id, p.name, p.slug, p.content, p.category_id, p.cateogry_name FROM post p JOIN category c ON c.id = p.category_id WHERE p.id = ?';
$stmt = $pdo->prepare($sql);
$stmt->bindParam(1, $_GET['id']);
$stmt->execute();
$mapper = new DatabaseMapper();
$post = $mapper->map($stmt->fetch(), Post::class);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment