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

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

rennokki/dynamodb
=================

AWS DynamoDB Eloquent ORM for Laravel 7+

1.6.1(5y ago)1827.1k↑540%2MITPHP

Since Dec 10Pushed 5y ago1 watchersCompare

[ Source](https://github.com/renoki-co/dynamodb)[ Packagist](https://packagist.org/packages/rennokki/dynamodb)[ RSS](/packages/rennokki-dynamodb/feed)WikiDiscussions master Synced yesterday

READMEChangelog (8)Dependencies (8)Versions (9)Used By (0)

[![CI](https://github.com/renoki-co/dynamodb/workflows/CI/badge.svg?branch=master)](https://github.com/renoki-co/dynamodb/workflows/CI/badge.svg?branch=master)[![Latest Stable Version](https://camo.githubusercontent.com/e43402f147e5e5099f72067b05bad0d4a6a9d65af86d256daa887391a8ddc46e/68747470733a2f2f706f7365722e707567782e6f72672f72656e6e6f6b6b692f64796e616d6f64622f762f737461626c65)](https://packagist.org/packages/rennokki/dynamodb)[![Total Downloads](https://camo.githubusercontent.com/3afc1b8667f5b68c37994a23075b102789f19eccaf7b0126287c3e2228e228d3/68747470733a2f2f706f7365722e707567782e6f72672f72656e6e6f6b6b692f64796e616d6f64622f646f776e6c6f616473)](https://packagist.org/packages/rennokki/dynamodb)[![Monthly Downloads](https://camo.githubusercontent.com/d96895bca9eac0f686a77f2865c1092db58f76d7989040324a141a61efb9bf25/68747470733a2f2f706f7365722e707567782e6f72672f72656e6e6f6b6b692f64796e616d6f64622f642f6d6f6e74686c79)](https://packagist.org/packages/rennokki/dynamodb)[![codecov](https://camo.githubusercontent.com/15e6375c707783ddd26e60471e92f74671ffb8211a88d222d2e5670e97a48531/68747470733a2f2f636f6465636f762e696f2f67682f72656e6f6b692d636f2f64796e616d6f64622f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/renoki-co/dynamodb/branch/master)[![StyleCI](https://camo.githubusercontent.com/b071c5c4b2a3e294317822791310e51b92f74092615d1a0a453ed3d162572cbd/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3232333233363738352f736869656c643f6272616e63683d6d6173746572)](https://github.styleci.io/repos/223236785)

Laravel DynamoDB
================

[](#laravel-dynamodb)

This package is a fork from [the original package by Bao Pham](https://github.com/baopham/laravel-dynamodb).

> For advanced users only. If you're not familiar with Laravel, [Laravel Eloquent](https://laravel.com/docs/eloquent) and [DynamoDB](https://aws.amazon.com/dynamodb/), then I suggest that you get familiar with those first.

- [Laravel DynamoDB](#laravel-dynamodb)
- [Install](#install)
- [Install (for Lumen)](#install-for-lumen)
- [Usage](#usage)
    - [Extend your Model](#extend-your-model)
    - [Add Trait to Model (to Sync)](#add-trait-to-model-to-sync)
- [Query Builder](#query-builder)
- [AWS SDK](#aws-sdk)
- [Supported features](#supported-features)
    - [find() and delete()](#find-and-delete)
    - [Conditions](#conditions)
        - [whereNull() and whereNotNull()](#wherenull-and-wherenotnull)
    - [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)
    - [getItemsCount()](#getitemscount)
    - [Query Scope](#query-scope)
    - [REMOVE — Deleting Attributes From An Item](#remove--deleting-attributes-from-an-item)
    - [toSql()](#tosql)
    - [Decorate Query](#decorate-query)
- [Indexes](#indexes)
- [Composite Keys](#composite-keys)
- [Query Builder](#query-builder-1)
- [FAQ](#faq)
    - [Security](#security)
    - [Credits](#credits)
    - [License](#license)

Install
=======

[](#install)

Install the package using Composer:

```
$ composer require rennokki/dynamodb
```

If your Laravel package does not support auto-discovery, add this to your `config/app.php` file:

```
'providers' => [
    ...
    Rennokki\DynamoDb\DynamoDbServiceProvider::class,
    ...****
];
```

Publish the config files.

```
php artisan vendor:publish
```

Install (for Lumen)
===================

[](#install-for-lumen)

For Lumen, try [this](https://github.com/laravelista/lumen-vendor-publish) to install the `vendor:publish` command and 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 Eloquent support
$app->withEloquent();
```

Usage
=====

[](#usage)

Extend your Model
-----------------

[](#extend-your-model)

Extend your model with `Rennokki\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.

```
use Rennokki\DynamoDb\DynamoDbModel;

class MyModel extends DynamoDbModel
{
    //
}
```

Add Trait to Model (to Sync)
----------------------------

[](#add-trait-to-model-to-sync)

To sync your DB table with a DynamoDb table, use trait `Rennokki\DynamoDb\ModelTrait`. This trait will call a `PutItem` after the model is saved, update or deleted.

```
use Rennokki\DynamoDb\ModelTrait as DynamoDbable;

class MyModel extends Model
{
    use DynamoDbable;
}
```

Query Builder
=============

[](#query-builder)

You can use the [query builder](#query-builder) facade to build more complex queries.

AWS SDK
=======

[](#aws-sdk)

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();
```

getItemsCount()
---------------

[](#getitemscount)

```
// returns the approximate total count of the table items
$total = Model::getItemsCount(); // ex: 5
```

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;
```

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

Decorate Query
--------------

[](#decorate-query)

Use `decorate` when you want to enhance the query.

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

```
/**
 * The DynamoDb 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, for the following query, `count_index` will be used:

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

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

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-1)

Use `DynamoDb` facade to build raw queries.

```
use Rennokki\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')
    ->setIndex('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();
```

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.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [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)
- [Alex Renoki](https://github.com/rennokki)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity36

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 98.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 ~57 days

Recently: every ~92 days

Total

8

Last Release

1990d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/21983456?v=4)[rennokki](/maintainers/rennokki)[@rennokki](https://github.com/rennokki)

---

Top Contributors

[![rennokki](https://avatars.githubusercontent.com/u/21983456?v=4)](https://github.com/rennokki "rennokki (52 commits)")[![stasadev](https://avatars.githubusercontent.com/u/24270994?v=4)](https://github.com/stasadev "stasadev (1 commits)")

---

Tags

amazonawsbuildercomposite-keysdynamodblaravellaravel-dynamodbqueryquery-builderlaravelamazonawsdynamodbquery

### Embed Badge

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

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

###  Alternatives

[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M194](/packages/laravel-ai)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[yajra/laravel-oci8

Oracle DB driver for Laravel via OCI8

8793.2M25](/packages/yajra-laravel-oci8)[baopham/dynamodb

Eloquent syntax for DynamoDB

4986.0M6](/packages/baopham-dynamodb)[spatie/laravel-health

Monitor the health of a Laravel application

87512.0M165](/packages/spatie-laravel-health)[glushkovds/phpclickhouse-laravel

Adapter of the most popular library https://github.com/smi2/phpClickHouse to Laravel

2051.5M2](/packages/glushkovds-phpclickhouse-laravel)

PHPackages © 2026

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