PHPackages                             thebatclaudio/dynamodb - 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. thebatclaudio/dynamodb

Abandoned → [baopham/laravel-dynamodb](/?search=baopham%2Flaravel-dynamodb)Library[Database &amp; ORM](/categories/database)

thebatclaudio/dynamodb
======================

Eloquent syntax for DynamoDB

6.1.4(3y ago)068.0kMITPHP

Since Aug 4Pushed 1y agoCompare

[ Source](https://github.com/thebatclaudio/laravel-dynamodb)[ Packagist](https://packagist.org/packages/thebatclaudio/dynamodb)[ RSS](/packages/thebatclaudio-dynamodb/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (4)Versions (80)Used By (0)

laravel-dynamodb
================

[](#laravel-dynamodb)

[![Latest Stable Version](https://camo.githubusercontent.com/8fbe86ae1b6f274d7efae9293dab388e6b078f82177cf60384cfa5b4d0f6fb01/68747470733a2f2f706f7365722e707567782e6f72672f62616f7068616d2f64796e616d6f64622f762f737461626c65)](https://packagist.org/packages/baopham/dynamodb)[![Total Downloads](https://camo.githubusercontent.com/1d75e034de9f69bcfd1816c091bc095a495c26ca0c21757cc4a850b0accaea4f/68747470733a2f2f706f7365722e707567782e6f72672f62616f7068616d2f64796e616d6f64622f646f776e6c6f616473)](https://packagist.org/packages/baopham/dynamodb)[![Latest Unstable Version](https://camo.githubusercontent.com/29d275ea5bc54a0d450a7943d5a749232f08c626f4dfcec5e7a513cc7bbe1154/68747470733a2f2f706f7365722e707567782e6f72672f62616f7068616d2f64796e616d6f64622f762f756e737461626c65)](https://packagist.org/packages/baopham/dynamodb)[![Build Status](https://camo.githubusercontent.com/f77907dee41a3a1e10e15dfe6c5201bbd59b06cd769d8c42540511c940cb8c61/68747470733a2f2f7472617669732d63692e6f72672f62616f7068616d2f6c61726176656c2d64796e616d6f64622e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/baopham/laravel-dynamodb)[![Code Coverage](https://camo.githubusercontent.com/3a9cf6054a906dfb1663090bb63314fde8441ace4500e0a6382490ba27e62cd5/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f62616f7068616d2f6c61726176656c2d64796e616d6f64622f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/baopham/laravel-dynamodb/?branch=master)[![License](https://camo.githubusercontent.com/009b4a2ca8a011ae0b60c9aa2db2220b7060a31b8cb5497add740c3cd0c4ad92/68747470733a2f2f706f7365722e707567782e6f72672f62616f7068616d2f64796e616d6f64622f6c6963656e7365)](https://packagist.org/packages/baopham/dynamodb)

Supports all key types - primary hash key and composite keys.

> For advanced users only. If you're not familiar with Laravel, Laravel Eloquent and DynamoDB, then I suggest that you get familiar with those first.

**Breaking changes in v2: config no longer lives in config/services.php**

- [Install](#install)
- [Usage](#usage)
    - [find() and delete()](#find-and-delete)
    - [Conditions](#conditions)
    - [all() and first()](#all-and-first)
    - [Pagination](#pagination)
    - [update](#update) / [updateAsync()](#updateasync)
    - [save](#save) / [saveAsync()](#saveasync)
    - [delete](#delete) / [deleteAsync()](#deleteasync)
    - [chunk](#chunk)
    - [limit() and take()](#limit-and-take)
    - [firstOrFail()](#firstorfail)
    - [findOrFail()](#findorfail)
    - [refresh()](#refresh)
    - [Query scope](#query-scope)
    - [REMOVE — Deleting Attributes From An Item](#remove--deleting-attributes-from-an-item)
    - [toSql() Style](#tosql-style)
    - [Decorate Query](#decorate-query)
- [Indexes](#indexes)
- [Composite Keys](#composite-keys)
- [Query Builder](#query-builder)
- [Requirements](#requirements)
- [Migrate from v1 to v2](#migrate-from-v1-to-v2)
- [FAQ](#faq)
- [License](LICENSE)
- [Author and Contributors](#author-and-contributors)

Install
-------

[](#install)

- Composer install

    ```
    composer require baopham/dynamodb
    ```
- Install service provider (&lt; Laravel 5.5):

    ```
    // config/app.php

    'providers' => [
        ...
        BaoPham\DynamoDb\DynamoDbServiceProvider::class,
        ...
    ];
    ```
- Run

    ```
    php artisan vendor:publish --provider 'BaoPham\DynamoDb\DynamoDbServiceProvider'
    ```
- Update DynamoDb config in [config/dynamodb.php](config/dynamodb.php)

**For Lumen**

- Try [this](https://github.com/laravelista/lumen-vendor-publish) to install the `vendor:publish` command
- Load configuration file and enable Eloquent support in `bootstrap/app.php`:

    ```
    $app = new Laravel\Lumen\Application(
        realpath(__DIR__.'/../')
    );

    // Load dynamodb config file
    $app->configure('dynamodb');

    // Enable Facade support
    $app->withFacades();

    // Enable Eloquent support
    $app->withEloquent();
    ```

Usage
-----

[](#usage)

- Extends your model with `BaoPham\DynamoDb\DynamoDbModel`, then you can use Eloquent methods that are supported. The idea here is that you can switch back to Eloquent without changing your queries.
- Or if you want to sync your DB table with a DynamoDb table, use trait `BaoPham\DynamoDb\ModelTrait`, it will call a `PutItem` after the model is saved.
- Alternatively, you can use the [query builder](#query-builder) facade to build more complex queries.
- AWS SDK v3 for PHP uses guzzlehttp promises to allow for asynchronous workflows. Using this package you can run eloquent queries like [delete](#deleteasync), [update](#updateasync), [save](#saveasync) asynchronously on DynamoDb.

### Supported features:

[](#supported-features)

#### find() and delete()

[](#find-and-delete)

```
$model->find($id, array $columns = []);
$model->findMany($ids, array $columns = []);
$model->delete();
$model->deleteAsync()->wait();
```

#### Conditions

[](#conditions)

```
// Using getIterator()
// If 'key' is the primary key or a global/local index and it is a supported Query condition,
// will use 'Query', otherwise 'Scan'.
$model->where('key', 'key value')->get();

$model->where(['key' => 'key value']);

// Chainable for 'AND'.
$model->where('foo', 'bar')
    ->where('foo2', '!=', 'bar2')
    ->get();

// Chainable for 'OR'.
$model->where('foo', 'bar')
    ->orWhere('foo2', '!=', 'bar2')
    ->get();

// Other types of conditions
$model->where('count', '>', 0)->get();
$model->where('count', '>=', 0)->get();
$model->where('count', 'id = 'de305d54-75b4-431b-adb2-eb6b9e546014';
$model->save();
```

#### saveAsync()

[](#saveasync)

Saving single model asynchronously and waiting on the promise for completion.

```
$model = new Model();
// Define fillable attributes in your Model class.
$model->fillableAttr1 = 'foo';
$model->fillableAttr2 = 'bar';
// DynamoDb doesn't support incremented Id, so you need to use UUID for the primary key.
$model->id = 'de305d54-75b4-431b-adb2-eb6b9e546014';
$model->saveAsync()->wait();
```

Saving multiple models asynchronously and waiting on all of them simultaneously.

```
for($i = 0; $i < 10; $i++){
    $model = new Model();
    // Define fillable attributes in your Model class.
    $model->fillableAttr1 = 'foo';
    $model->fillableAttr2 = 'bar';
    // DynamoDb doesn't support incremented Id, so you need to use UUID for the primary key.
    $model->id = uniqid();
    // Returns a promise which you can wait on later.
    $promises[] = $model->saveAsync();
}

\GuzzleHttp\Promise\all($promises)->wait();
```

#### delete()

[](#delete)

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

#### deleteAsync()

[](#deleteasync)

```
$model->deleteAsync()->wait();
```

#### chunk()

[](#chunk)

```
$model->chunk(10, function ($records) {
    foreach ($records as $record) {

    }
});
```

#### limit() and take()

[](#limit-and-take)

```
// Use this with caution unless your limit is small.
// DynamoDB has a limit of 1MB so if your limit is very big, the results will not be expected.
$model->where('name', 'foo')->take(3)->get();
```

#### firstOrFail()

[](#firstorfail)

```
$model->where('name', 'foo')->firstOrFail();
// for composite key
$model->where('id', 'foo')->where('id2', 'bar')->firstOrFail();
```

#### findOrFail()

[](#findorfail)

```
$model->findOrFail('foo');
// for composite key
$model->findOrFail(['id' => 'foo', 'id2' => 'bar']);
```

#### refresh()

[](#refresh)

```
$model = Model::first();
$model->refresh();
```

#### Query Scope

[](#query-scope)

```
class Foo extends DynamoDbModel
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('count', function (DynamoDbQueryBuilder $builder) {
            $builder->where('count', '>', 6);
        });
    }

    public function scopeCountUnderFour($builder)
    {
        return $builder->where('count', '', 10)->toDynamoDbQuery();
// $op is either "Scan" or "Query"
$op = $raw->op;
// The query body being sent to AWS
$query = $raw->query;
```

where `$raw` is an instance of [RawDynamoDbQuery](./src/RawDynamoDbQuery.php)

#### Decorate Query

[](#decorate-query)

Use `decorate` when you want to enhance the query. For example:

To set the order of the sort key:

```
$items = $model
    ->where('hash', 'hash-value')
    ->where('range', '>', 10)
    ->decorate(function (RawDynamoDbQuery $raw) {
        // desc order
        $raw->query['ScanIndexForward'] = false;
    })
    ->get();
```

To force to use "Query" instead of "Scan" if the library fails to detect the correct operation:

```
$items = $model
    ->where('hash', 'hash-value')
    ->decorate(function (RawDynamoDbQuery $raw) {
        $raw->op = 'Query';
    })
    ->get();
```

Indexes
-------

[](#indexes)

If your table has indexes, make sure to declare them in your model class like so

```
/**
 * Indexes.
 * [
 *     '' => [
 *          'hash' => ''
 *     ],
 *     '' => [
 *          'hash' => '',
 *          'range' => ''
 *     ],
 * ]
 *
 * @var array
 */
protected $dynamoDbIndexKeys = [
    'count_index' => [
        'hash' => 'count'
    ],
];
```

Note that order of index matters when a key exists in multiple indexes.
For example, we have this

```
$model->where('user_id', 123)->where('count', '>', 10)->get();
```

with

```
protected $dynamoDbIndexKeys = [
    'count_index' => [
        'hash' => 'user_id',
        'range' => 'count'
    ],
    'user_index' => [
        'hash' => 'user_id',
    ],
];
```

will use `count_index`.

```
protected $dynamoDbIndexKeys = [
    'user_index' => [
        'hash' => 'user_id',
    ],
    'count_index' => [
        'hash' => 'user_id',
        'range' => 'count'
    ]
];
```

will use `user_index`.

Most of the time, you should not have to do anything but if you need to use a specific index, you can specify it like so

```
$model->where('user_id', 123)->where('count', '>', 10)->withIndex('count_index')->get();
```

Composite Keys
--------------

[](#composite-keys)

To use composite keys with your model:

- Set `$compositeKey` to an array of the attributes names comprising the key, e.g.

```
protected $primaryKey = 'customer_id';
protected $compositeKey = ['customer_id', 'agent_id'];
```

- To find a record with a composite key

```
$model->find(['customer_id' => 'value1', 'agent_id' => 'value2']);
```

Query Builder
-------------

[](#query-builder)

Use `DynamoDb` facade to build raw queries

```
use BaoPham\DynamoDb\Facades\DynamoDb;

DynamoDb::table('articles')
    // call set to build the query body to be sent to AWS
    ->setFilterExpression('#name = :name')
    ->setExpressionAttributeNames(['#name' => 'author_name'])
    ->setExpressionAttributeValues([':name' => DynamoDb::marshalValue('Bao')])
    ->prepare()
    // the query body will be sent upon calling this.
    ->scan(); // supports any DynamoDbClient methods (e.g. batchWriteItem, batchGetItem, etc.)

DynamoDb::table('articles')
    ->setIndexName('author_name')
    ->setKeyConditionExpression('#name = :name')
    ->setProjectionExpression('id, author_name')
    // Can set the attribute mapping one by one instead
    ->setExpressionAttributeName('#name', 'author_name')
    ->setExpressionAttributeValue(':name', DynamoDb::marshalValue('Bao'))
    ->prepare()
    ->query();

DynamoDb::table('articles')
    ->setKey(DynamoDb::marshalItem(['id' => 'ae025ed8']))
    ->setUpdateExpression('REMOVE #c, #t')
    ->setExpressionAttributeName('#c', 'comments')
    ->setExpressionAttributeName('#t', 'tags')
    ->prepare()
    ->updateItem();

DynamoDb::table('articles')
    ->setKey(DynamoDb::marshalItem(['id' => 'ae025ed8']))
    ->prepare()
    ->deleteItem();

DynamoDb::table('articles')
    ->setItem(DynamoDb::marshalItem(['id' => 'ae025ed8', 'author_name' => 'New Name']))
    ->prepare()
    ->putItem();

// Or, instead of ::table()
DynamoDb::newQuery()
    ->setTableName('articles')

// Or access the DynamoDbClient instance directly
DynamoDb::client();
// pass in the connection name to get a different client instance other than the default.
DynamoDb::client('test');
```

The query builder methods are in the form of `set`, where `` is the key name of the query body to be sent.

For example, to build an [`UpdateTable`](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#updatetable) query:

```
[
    'AttributeDefinitions' => ...,
    'GlobalSecondaryIndexUpdates' => ...,
    'TableName' => ...
]
```

Do:

```
$query = DynamoDb::table('articles')
    ->setAttributeDefinitions(...)
    ->setGlobalSecondaryIndexUpdates(...);
```

And when ready:

```
$query->prepare()->updateTable();
```

Requirements
------------

[](#requirements)

Laravel ^5.1

Migrate from v1 to v2
---------------------

[](#migrate-from-v1-to-v2)

Follow these steps:

1. Update your `composer.json` to use v2
2. Run `composer update`
3. Run `php artisan vendor:publish`
4. Move your DynamoDb config in `config/services.php` to the new config file `config/dynamodb.php` as one of the connections
    1. Move `key`, `secret`, `token` inside `credentials`
    2. Rename `local_endpoint` to `endpoint`
    3. Remove `local` field

FAQ
---

[](#faq)

Q: Cannot assign `id` property if its not in the fillable array
A: Try [this](https://github.com/baopham/laravel-dynamodb/issues/10)?

Q: How to create migration?
A: Please see [this issue](https://github.com/baopham/laravel-dynamodb/issues/90)

Q: How to use with factory?
A: Please see [this issue](https://github.com/baopham/laravel-dynamodb/issues/111)

Q: How do I use with Job? Getting a SerializesModels error
A: You can either [write your own restoreModel](https://github.com/baopham/laravel-dynamodb/issues/132) or remove the `SerializesModels` trait from your Job.

Author and Contributors
-----------------------

[](#author-and-contributors)

- [Bao Pham](https://github.com/baopham/laravel-dynamodb)
- [warrick-loyaltycorp](https://github.com/warrick-loyaltycorp)
- [Alexander Ward](https://github.com/cthos)
- [Quang Ngo](https://github.com/vanquang9387)
- [David Higgins](https://github.com/zoul0813)
- [Damon Williams](https://github.com/footballencarta)
- [David Palmer](https://github.com/dp88)

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance26

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 72% 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 ~36 days

Recently: every ~184 days

Total

73

Last Release

1318d ago

Major Versions

v1.x-dev → 2.0.32017-10-19

2.0.3 → 3.0.02017-11-24

3.0.1 → 4.0.02017-11-25

4.12.0 → 5.0.02020-01-21

5.0.1 → 6.0.02020-03-23

### Community

Maintainers

![](https://www.gravatar.com/avatar/658b4ac9d0fe638b561a8e49e3fb409298206ec6e98cd9276cd93f98d65686b6?d=identicon)[thebatclaudio](/maintainers/thebatclaudio)

---

Top Contributors

[![baopham](https://avatars.githubusercontent.com/u/783410?v=4)](https://github.com/baopham "baopham (242 commits)")[![vanquang9387](https://avatars.githubusercontent.com/u/7125810?v=4)](https://github.com/vanquang9387 "vanquang9387 (14 commits)")[![zoul0813](https://avatars.githubusercontent.com/u/1064917?v=4)](https://github.com/zoul0813 "zoul0813 (13 commits)")[![warrick-loyaltycorp](https://avatars.githubusercontent.com/u/16530482?v=4)](https://github.com/warrick-loyaltycorp "warrick-loyaltycorp (12 commits)")[![JackPriceBurns](https://avatars.githubusercontent.com/u/5484580?v=4)](https://github.com/JackPriceBurns "JackPriceBurns (10 commits)")[![michaelshaffer37](https://avatars.githubusercontent.com/u/12464025?v=4)](https://github.com/michaelshaffer37 "michaelshaffer37 (7 commits)")[![nelson6e65](https://avatars.githubusercontent.com/u/9272498?v=4)](https://github.com/nelson6e65 "nelson6e65 (5 commits)")[![cthos](https://avatars.githubusercontent.com/u/456545?v=4)](https://github.com/cthos "cthos (4 commits)")[![sahilsharma011](https://avatars.githubusercontent.com/u/9516206?v=4)](https://github.com/sahilsharma011 "sahilsharma011 (3 commits)")[![fd-automox](https://avatars.githubusercontent.com/u/64211280?v=4)](https://github.com/fd-automox "fd-automox (2 commits)")[![teeedwards](https://avatars.githubusercontent.com/u/117519304?v=4)](https://github.com/teeedwards "teeedwards (2 commits)")[![pellaras](https://avatars.githubusercontent.com/u/14969790?v=4)](https://github.com/pellaras "pellaras (2 commits)")[![frank-amsterdam](https://avatars.githubusercontent.com/u/56869801?v=4)](https://github.com/frank-amsterdam "frank-amsterdam (2 commits)")[![footballencarta](https://avatars.githubusercontent.com/u/1312258?v=4)](https://github.com/footballencarta "footballencarta (2 commits)")[![tudor2004](https://avatars.githubusercontent.com/u/2884281?v=4)](https://github.com/tudor2004 "tudor2004 (1 commits)")[![xabbuh](https://avatars.githubusercontent.com/u/1957048?v=4)](https://github.com/xabbuh "xabbuh (1 commits)")[![mlcollins10](https://avatars.githubusercontent.com/u/1544921?v=4)](https://github.com/mlcollins10 "mlcollins10 (1 commits)")[![crhg](https://avatars.githubusercontent.com/u/8174597?v=4)](https://github.com/crhg "crhg (1 commits)")[![dp88](https://avatars.githubusercontent.com/u/3003563?v=4)](https://github.com/dp88 "dp88 (1 commits)")[![Dylan-DPC](https://avatars.githubusercontent.com/u/99973273?v=4)](https://github.com/Dylan-DPC "Dylan-DPC (1 commits)")

---

Tags

laravelawsdynamodb

### Embed Badge

![Health badge](/badges/thebatclaudio-dynamodb/health.svg)

```
[![Health](https://phpackages.com/badges/thebatclaudio-dynamodb/health.svg)](https://phpackages.com/packages/thebatclaudio-dynamodb)
```

###  Alternatives

[aws/aws-sdk-php-laravel

A simple Laravel 9/10/11/12/13 service provider for including the AWS SDK for PHP.

1.7k35.6M75](/packages/aws-aws-sdk-php-laravel)[baopham/dynamodb

Eloquent syntax for DynamoDB

4975.7M6](/packages/baopham-dynamodb)[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[kitar/laravel-dynamodb

A DynamoDB based Eloquent model and Query builder for Laravel.

193675.3k1](/packages/kitar-laravel-dynamodb)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)

PHPackages © 2026

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