PHPackages                             autoprotect-group/php-dynamodb-odm - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. autoprotect-group/php-dynamodb-odm

ActiveLibrary[Database &amp; ORM](/categories/database)

autoprotect-group/php-dynamodb-odm
==================================

PHP Object Document Mapper for AWS DynamoDB

v1.1.3(1y ago)44243Apache-2.0PHPPHP ^8.1

Since Jun 1Pushed 1y ago4 watchersCompare

[ Source](https://github.com/AutoProtect-Group/php-dynamodb-odm)[ Packagist](https://packagist.org/packages/autoprotect-group/php-dynamodb-odm)[ RSS](/packages/autoprotect-group-php-dynamodb-odm/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (12)Versions (11)Used By (0)

AWS Dynamodb ODM for PHP
========================

[](#aws-dynamodb-odm-for-php)

[![Code style, unit and functional tests](https://github.com/AutoProtect-Group/php-dynamodb-odm/actions/workflows/ci.yml/badge.svg)](https://github.com/AutoProtect-Group/php-dynamodb-odm/actions/workflows/ci.yml/badge.svg)

This is a library and an Object Document Mapper to use with AWS DynamoDB in a more convenient way.

Usage
-----

[](#usage)

### Configure the ODM

[](#configure-the-odm)

Set up native client:

```
$dynamoDbClient = new DynamoDbClient(array_merge(
    [
        'region' => 'eu-west-2',
        'version' => 'latest',
    ]
));
```

Set up the main operations lib client:

```
$client = new DynamodbOperationsClient($dynamoDbClient);
```

Set up the marshaller. Native AWS marshaller may be taken:

```
$marshaler = new Marshaler();
```

Set up the Query builder:

```
$queryBuilder = new QueryBuilder($marshaler, new ExpressionFactory($marshaler));
```

Set up annotation reader and annotation manager:

```
// annotation reader
$annotationReader = new AnnotationReader();

// annotation manager
$annotationManager = new AnnotationManager($annotationReader);
```

The hydrators for the models:

```
$newModelHydrator = new Hydrator(NewModel::class, $annotationManager);
$sortKeyModelHydrator = new Hydrator(SortKeyModel::class, $annotationManager);
```

Serializer for inserting records into DB:

```
// serializer for
$serializer = new Serializer($annotationManager);
```

The full example is in [here](examples/initialise_client.php).

### Model

[](#model)

#### Model field types

[](#model-field-types)

The lib operates with models. Each model may have various supported field types. Here is a list of types which correlate with PHP and Dynamodb types:

- `BooleanType`: boolean for DynamoDb and for php
- `CollectionType`: list for DynamoDb, in php it's an array list of items of specific model
- `DateType`: string for DynamoDb, DateTime for php
- `EnumType`: string for DynamoDb, enum for php
- `FloatType`: number for DynamoDb, float for php
- `HashMapType`: map for DynamoDb, in php it's associative array of items of specific model
- `IntegerType`: number for DynamoDb, int for php
- `ModelType`: map for DynamoDb, instance of model for php
- `Money`: map for DynamoDb, special MoneyObject for PHP. [Money value](https://martinfowler.com/eaaCatalog/money.html) as a concept
- `NumberType`: number for DynamoDb. An abstract type, not a handy one. My be used occasionally
- `ScalarCollectionType`: map for DynamoDb. in php it's associative array of any dynamodb compatible types excluding `CollectionType`, `HashMapType` or `ModelType`
- `StringType`: string for DynamoDb and for php

Here is a model example:

```
class ExampleDemoModel extends Model
{
    protected const TABLE_NAME = 'test-table';

    // Primary means that this is a partition key for the DynamoDb table
    #[StringType, Primary]  protected string $id;
    #[StringType]           protected string $name;
    #[FloatType]            protected float $price;
    #[Money]                protected Money $priceNet;
    #[FloatType]            protected float $percent;
    #[IntegerType]          protected int $itemsAmount;
    #[DateType]             protected DateTime $createdAt;
    #[BooleanType]          protected bool $isDeleted;
    #[BooleanType]          protected bool $isPhoneNumber;
    #[ModelType([ModelType::MODEL_CLASS_NAME => RelatedModel::class])]
    protected RelatedModel $buyer;
    #[CollectionType([CollectionType::MODEL_CLASS_NAME => RelatedModel::class])]
    protected array $buyers;
    #[ModelType([Asset::MODEL_CLASS_NAME => Asset::class])]
    protected Asset $asset;
    #[HashMapType([HashMapType::MODEL_CLASS_NAME => RelatedModel::class])]
    protected array $buyersMap;

    // getter and setters should be here
 }
```

Model full example is here: [model.php](examples/model.php)

#### Enumerations example

[](#enumerations-example)

Enumerations are also supported. Here is an example of the model with enumeration fields:

```
class ModelWithEnumeration extends Model
{
    #[Primary, StringType]
    protected string $id;

    #[EnumType]
    protected OrderStatus $orderStatus;

    // union types
    #[EnumType]
    protected OrderStatus|ApplicationStatus $unionStatus;

    // union types with null
    #[EnumType]
    protected OrderStatus|ApplicationStatus|null $unionNullableStatus;

    // isStrict means the value will be null in case wrong value comes from the DB
    #[EnumType(isStrict: false)]
    protected ?OrderStatus $orderStatusAdditional = null;

    #[EnumType]
    protected CustomerType $customerType;
}
```

#### Fields encryption

[](#fields-encryption)

Certain types custom encryption is supported. In case there are some fields which needs to be encrypted.

First of all we need to create a custom encryptor:

```
MyEncryptor implements EncryptorInterface {
    protected const ENCRYPTION_KEY = 'def000008053addc0f94b14c0e480a10631a0a970b3565e5a7a2aeaeeb51a39e2d139a8977bc02be0195f0036a29aefff9df6d2ddb81432d14b4dce82b83b3a95c6d0205';

    public function decrypt(string|array $encryptedData, array $options = []): string|array
    {
        // any decryption way may be implemented
        if (is_array($encryptedData)) {
            // ...specific property decryption operations...
            return $encryptedData;
        }

        return Crypto::decrypt(
            $encryptedData,
            Key::loadFromAsciiSafeString(static::ENCRYPTION_KEY)
        );
    }
}
```

Then the decryptor should be passed into the hydrator:

```
$newModelHydrator = new Hydrator(
    EncryptionDemoModel::class,
    $annotationManager,
    new MyEncryptor(),
);
```

And the model may be the following:

```
class EncryptionDemoModel extends Model
{
    #[Key\Primary, Types\StringType]
    protected string $id;

    // ability to encrypt a specific property in a scalar associative  array
    #[Types\ScalarCollectionType, Encrypted(["encryptedProperty" => "secretProperty"])]
    protected array $encryptedArray;

    #[Types\StringType, Encrypted]
    protected string $encryptedName;
}
```

### Set up the repository for your model

[](#set-up-the-repository-for-your-model)

The best way to operate with records is to create a repository. There is a built-in already:

```
$newModelDynamoDbRepository = new DynamoDBRepository(
    NewModel::class,
    $client,
    $queryBuilder,
    $newModelHydrator,
    $annotationManager,
    $marshaler,
    $serializer
);
```

There are built-in operation in the default repository.

#### Get model by partition Id

[](#get-model-by-partition-id)

##### Just by partition key

[](#just-by-partition-key)

```
$foundModel = $newModelDynamoDbRepository->get($id);
```

##### By partition key and sort key

[](#by-partition-key-and-sort-key)

```
$foundModel = $newModelDynamoDbRepository->get($id, $sortKey);
```

##### Non-consistent read

[](#non-consistent-read)

```
$foundModel = $newModelDynamoDbRepository->get($id, $sortKey, false);
```

##### Get one item

[](#get-one-item)

```
$foundModel = $newModelDynamoDbRepository->getOneById($id, $sortKey, false);
```

#### Insert model

[](#insert-model)

```
$newModelDynamoDbRepository->save($model);
```

#### Delete item

[](#delete-item)

```
$newModelDynamoDbRepository->delete($model);
```

### Document repository

[](#document-repository)

Sometimes we need to fetch not the whole model, but just a part of it. For this purpose there is such called `DocumentRepository`. The part of the document may be technically fetched using native DynamoDb projection expressions.

Setting `DocumentRepository` up:

```
$documentRepository = new DocumentRepository(
    NewModelNested::class,
    $client,
    $this->queryBuilder,
    $this->newModelHydrator,
    $annotationManager,
    $marshaler,
    $serializer
);
```

#### Get a model by projection expression

[](#get-a-model-by-projection-expression)

```
$projectionExpression = "property.subPropertyModel";

$model = $documentRepository->getDocument()
    ->setConsistentRead(true)
    ->withAttrPath($projectionExpression)
    ->withPrKey($keyValue)
    ->execute()
;
```

#### Get a specific scalar property by projection expression

[](#get-a-specific-scalar-property-by-projection-expression)

```
$projectionExpression = "property.subPropertyModel.name";

$name = $this->documentRepository->getDocumentProperty()
    ->setConsistentRead(true)
    ->withAttrPath($projection)
    ->withPrKey($keyValue)
    ->execute()
;
```

#### Get/create/update/delete operations

[](#getcreateupdatedelete-operations)

Document repository supports specific property get/create/update/delete operations:

- `createDocument()`
- `updateDocument()`
- `removeDocument()`
- `getDocumentCollection()`
- `updateDocumentCollection()`
- `createDocumentCollection()`

### Query builder

[](#query-builder)

Another powerful feature is query builders. This adds flexibility to fetch items by specific criteria which is supported by DynamoDB.

This is a way to work with the Dynamodb using raw queries and results

#### Get query builder

[](#get-query-builder)

Fetch items:

```
$getItemQuery = $queryBuilder
    ->getItem(self::DB_TABLE)
    ->itemKey([$itemKey => $keyValue])
    ->getQuery();

$item = $this->dynamoDbClient
    ->getItem($getItemQuery)->get('Item');
```

#### Update query builder

[](#update-query-builder)

Ability to update specific attributes.

```
$attributesForUpdate = [
   "numberProp" => 2,
   "stringProp" => "updated string value",
   "hashMapProp.map-id-1.type" => "updated map-type-1",
   "hashMapProp.map-id-1.mapProp" => "updated mapProp",
   "listProp" => [
         "updated listProp 1",
         "updated listProp 2"
      ]
];

$getItemQuery = $queryBuilder
    ->updateItem(self::DB_TABLE)
    ->itemKey([$itemKey => $keyValue])
    ->attributes($attributesForUpdate)
    ->getQuery();

$dynamoDbClient->updateItem($getItemQuery);
```

Local dev environment installation
----------------------------------

[](#local-dev-environment-installation)

1. In order to build a dev image, please, run:

```
docker-compose build
```

2. Then run to install dependencies:

```
docker-compose run --no-deps dynamodb-odm composer install
```

Running tests
-------------

[](#running-tests)

### Unit tests

[](#unit-tests)

This package uses phpspec for running unit tests.

Run them using the following way:

```
docker-compose run --no-deps dynamodb-odm vendor/bin/phpspec run
```

One can use environment variables in the `.env.local` file to be able to debug the library. For this just Copy file [.env.local.sample](.env.local.sample) into [.env.local](.env.local) and set up the variable according to your OS.

And then run the tests with:

```
docker-compose --env-file ./.env.local run  --no-deps dynamodb-odm vendor/bin/phpspec run
```

### Functional tests

[](#functional-tests)

This package uses behat for running functional tests.

Then just run the tests:

```
docker-compose run dynamodb-odm vendor/bin/behat -c behat.yml --stop-on-failure
```

### Syntax check tests

[](#syntax-check-tests)

You need to check if the code style is OK by running:

```
docker-compose run --no-deps dynamodb-odm vendor/bin/phpcs --standard=/application/phpcs.xml
```

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance34

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 57.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~90 days

Recently: every ~113 days

Total

6

Last Release

627d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5e68462bd35d4a631e6a898283983361f6087f3f2ce2bd353ebe3c4b41f33861?d=identicon)[gep](/maintainers/gep)

---

Top Contributors

[![gep](https://avatars.githubusercontent.com/u/223114?v=4)](https://github.com/gep "gep (4 commits)")[![petergodmanap](https://avatars.githubusercontent.com/u/87810427?v=4)](https://github.com/petergodmanap "petergodmanap (2 commits)")[![GinoPane](https://avatars.githubusercontent.com/u/3897579?v=4)](https://github.com/GinoPane "GinoPane (1 commits)")

---

Tags

awsdynamodbobject-document-mapperodmphpphp81

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/autoprotect-group-php-dynamodb-odm/health.svg)

```
[![Health](https://phpackages.com/badges/autoprotect-group-php-dynamodb-odm/health.svg)](https://phpackages.com/packages/autoprotect-group-php-dynamodb-odm)
```

###  Alternatives

[baopham/dynamodb

Eloquent syntax for DynamoDB

4975.7M6](/packages/baopham-dynamodb)[doctrine/doctrine-module

Laminas Module that provides Doctrine basic functionality required for ORM and ODM modules

3957.9M116](/packages/doctrine-doctrine-module)[kitar/laravel-dynamodb

A DynamoDB based Eloquent model and Query builder for Laravel.

193675.3k1](/packages/kitar-laravel-dynamodb)[thecodingmachine/tdbm

The Database Machine is a PHP ORM that requires no configuration. The object model is deduced from the database model.

123174.9k6](/packages/thecodingmachine-tdbm)[scottlaurent/accounting

Laravel Accounting Journals for Eloquent Models

20251.8k](/packages/scottlaurent-accounting)[nettrine/annotations

Doctrine Annotations for Nette Framework

193.0M7](/packages/nettrine-annotations)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
