Skip to content
This repository has been archived by the owner on Oct 28, 2022. It is now read-only.

Commit

Permalink
Refactor to access items using the class name instead of the table name
Browse files Browse the repository at this point in the history
  • Loading branch information
mnapoli committed Apr 26, 2019
1 parent fdbfd02 commit b4f2712
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 81 deletions.
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,23 @@ $dynamap = Dynamap::fromOptions([

$dynamap->save($myObject);

$myObject = $dynamap->find('table', 'key');
$myObject = $dynamap->get('table', 'key'); // Same as `find()` but throws an exception if not found
$myObject = $dynamap->find(MyClass::class, 'key');
$myObject = $dynamap->get(MyClass::class, 'key'); // Same as `find()` but throws an exception if not found

$objects = $dynamap->getAll('table');
$objects = $dynamap->getAll(MyClass::class);
```

Mapping example:

```php
$mapping = [
Article::class => [
'table' => 'articles',
'keys' => [
'id',
],
],
];
```

Supported field types:
Expand Down
45 changes: 22 additions & 23 deletions src/Dynamap.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class Dynamap
private $dynamoDb;

/** @var Mapping */
private $mappingObj;
private $mapping;

public function __construct(DynamoDbClient $dynamoDb, array $mapping)
{
$this->dynamoDb = $dynamoDb;
$this->mappingObj = new Mapping($mapping);
$this->mapping = new Mapping($mapping);
}

public static function fromOptions(array $options, array $mapping): self
Expand All @@ -28,13 +28,15 @@ public static function fromOptions(array $options, array $mapping): self
return new static(new DynamoDbClient($options), $mapping);
}

public function getAll(string $table): array
public function getAll(string $class): array
{
$tableMapping = $this->mapping->getTableMapping($class);

$items = $this->dynamoDb->scan([
'TableName' => $table,
'TableName' => $tableMapping->getTableName(),
])['Items'];

return $this->mapList($items, $table);
return $this->mapList($items, $tableMapping);
}

/**
Expand All @@ -46,13 +48,11 @@ public function getAll(string $table): array
* @throws \InvalidArgumentException If the key is invalid.
* @throws ItemNotFound If the item cannot be found.
*/
public function get(string $table, $key): object
public function get(string $class, $key): object
{
$item = $this->find($table, $key);

$item = $this->find($class, $key);
if ($item === null) {
$tableMapping = $this->mappingObj->getTableMapping($table);
throw ItemNotFound::fromKey($tableMapping->getClassName(), $key);
throw ItemNotFound::fromKey($class, $key);
}

return $item;
Expand All @@ -66,9 +66,10 @@ public function get(string $table, $key): object
* @param int|string|array $key
* @throws \InvalidArgumentException If the key is invalid.
*/
public function find(string $table, $key): ?object
public function find(string $class, $key): ?object
{
$tableMapping = $this->mappingObj->getTableMapping($table);
$tableMapping = $this->mapping->getTableMapping($class);
$table = $tableMapping->getTableName();

try {
$item = $this->dynamoDb->getItem([
Expand All @@ -86,13 +87,13 @@ public function find(string $table, $key): ?object
return null;
}

return $this->map($item, $table);
return $this->map($item, $tableMapping);
}

public function save(object $object): void
{
$reflectedObject = new \ReflectionObject($object);
$tableMapping = $this->mappingObj->getTableFromClassName($reflectedObject->getName());
$tableMapping = $this->mapping->getTableMapping($reflectedObject->getName());

$item = [];
foreach ($tableMapping->getKeyMapping() as $fieldMapping) {
Expand Down Expand Up @@ -131,9 +132,9 @@ public function save(object $object): void
* @param array $values Key-value map
* @throws \Exception
*/
public function partialUpdate(string $table, $itemKey, array $values): void
public function partialUpdate(string $class, $itemKey, array $values): void
{
$tableMapping = $this->mappingObj->getTableMapping($table);
$tableMapping = $this->mapping->getTableMapping($class);

$key = $this->buildKeyQuery($itemKey, $tableMapping);

Expand All @@ -148,24 +149,22 @@ public function partialUpdate(string $table, $itemKey, array $values): void
$updateExpression = 'set ' . implode(', ', $updateExpressionParts);

$this->dynamoDb->updateItem([
'TableName' => $table,
'TableName' => $tableMapping->getTableName(),
'Key' => $key,
'UpdateExpression' => $updateExpression,
'ExpressionAttributeValues' => $updateValues,
]);
}

private function mapList(array $items, string $table): array
private function mapList(array $items, TableMapping $tableMapping): array
{
return array_map(function (array $item) use ($table) {
return $this->map($item, $table);
return array_map(function (array $item) use ($tableMapping) {
return $this->map($item, $tableMapping);
}, $items);
}

private function map(array $item, string $table): object
private function map(array $item, TableMapping $tableMapping): object
{
$tableMapping = $this->mappingObj->getTableMapping($table);

$class = new \ReflectionClass($tableMapping->getClassName());
$object = $class->newInstanceWithoutConstructor();

Expand Down
59 changes: 30 additions & 29 deletions src/Mapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,49 @@

class Mapping
{
/** @var TableMapping[] */
/** @var array|TableMapping[] */
private $tables;
/** @var PropertyInfoExtractor|null */
private $propertyInfo;

public function __construct(array $mappingConfig)
{
$phpDocExtractor = new PhpDocExtractor;
$reflectionExtractor = new ReflectionExtractor;
$listExtractors = [$reflectionExtractor];
$typeExtractors = [$phpDocExtractor, $reflectionExtractor];
$descriptionExtractors = [$phpDocExtractor];
$accessExtractors = [$reflectionExtractor];
$propertyInitializableExtractors = [$reflectionExtractor];
$propertyInfo = new PropertyInfoExtractor(
$listExtractors,
$typeExtractors,
$descriptionExtractors,
$accessExtractors,
$propertyInitializableExtractors
);

foreach ($mappingConfig as $tableName => $tableConfig) {
$this->tables[$tableName] = new TableMapping($propertyInfo, $tableName, $tableConfig);
}
$this->tables = $mappingConfig; // lazy initialization
}

public function getTableMapping(string $table): TableMapping
public function getTableMapping(string $className): TableMapping
{
if (! isset($this->tables[$table])) {
throw new TableNotFound("The table `$table` is not configured in Dynamap");
if (! isset($this->tables[$className])) {
throw new TableNotFound("No table mapping found for class `$className`");
}

if (is_array($this->tables[$className])) {
$mapping = new TableMapping($this->propertyInfo(), $className, $this->tables[$className]);
$this->tables[$className] = $mapping;
}

return $this->tables[$table];
return $this->tables[$className];
}

public function getTableFromClassName(string $className): TableMapping
private function propertyInfo(): PropertyInfoExtractor
{
foreach ($this->tables as $tableMapping) {
if ($tableMapping->getClassName() === $className) {
return $tableMapping;
}
if (! $this->propertyInfo) {
$phpDocExtractor = new PhpDocExtractor;
$reflectionExtractor = new ReflectionExtractor;
$listExtractors = [$reflectionExtractor];
$typeExtractors = [$phpDocExtractor, $reflectionExtractor];
$descriptionExtractors = [$phpDocExtractor];
$accessExtractors = [$reflectionExtractor];
$propertyInitializableExtractors = [$reflectionExtractor];
$this->propertyInfo = new PropertyInfoExtractor(
$listExtractors,
$typeExtractors,
$descriptionExtractors,
$accessExtractors,
$propertyInitializableExtractors
);
}

throw new TableNotFound("No table mapping found for class `$className`");
return $this->propertyInfo;
}
}
10 changes: 7 additions & 3 deletions src/TableMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ class TableMapping
/** @var Field[] */
private $fields = [];

public function __construct(PropertyInfoExtractorInterface $propertyInfo, string $tableName, array $mappingConfig)
public function __construct(PropertyInfoExtractorInterface $propertyInfo, string $className, array $mappingConfig)
{
$this->propertyInfo = $propertyInfo;
$this->tableName = $tableName;
$this->className = (string) $mappingConfig['class'];
$this->className = $className;
$this->tableName = (string) $mappingConfig['table'];

$this->readProperties($this->className, $mappingConfig['keys']);
}
Expand Down Expand Up @@ -76,6 +76,10 @@ public function hasFieldOrKey(string $fieldName): bool

private function readProperties(string $className, array $keys): void
{
if (! class_exists($className)) {
throw new \Exception("The class `$className` doesn't exist");
}

$class = new \ReflectionClass($className);
foreach ($class->getProperties() as $propertyReflection) {
if ($propertyReflection->isStatic()) {
Expand Down
Loading

0 comments on commit b4f2712

Please sign in to comment.