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

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

laravie/eloquent-dynamodb
=========================

Eloquent syntax for DynamoDB

v1.3.1(6y ago)58.2k↓33.3%[1 issues](https://github.com/laravie/eloquent-dynamodb/issues)MITPHPPHP &gt;=7.2

Since Nov 12Pushed 5y ago1 watchersCompare

[ Source](https://github.com/laravie/eloquent-dynamodb)[ Packagist](https://packagist.org/packages/laravie/eloquent-dynamodb)[ Fund](https://paypal.me/crynobone)[ Patreon](https://www.patreon.com/crynobone)[ RSS](/packages/laravie-eloquent-dynamodb/feed)WikiDiscussions 1.x Synced 1mo ago

READMEChangelog (7)Dependencies (5)Versions (9)Used By (0)

Eloquent syntax for DynamoDB
============================

[](#eloquent-syntax-for-dynamodb)

[![Latest Stable Version](https://camo.githubusercontent.com/382a67af01575a24c9ff60cef63b4d18923a7b5ab0e71fee72a9bf0716216949/68747470733a2f2f706f7365722e707567782e6f72672f6c6172617669652f656c6f7175656e742d64796e616d6f64622f762f737461626c65)](https://packagist.org/packages/laravie/eloquent-dynamodb)[![Total Downloads](https://camo.githubusercontent.com/f51e09a5ed52b0e791814f6ac92bf5910aba50ee7d3d05e3a3cf5c5f3a7159db/68747470733a2f2f706f7365722e707567782e6f72672f6c6172617669652f656c6f7175656e742d64796e616d6f64622f646f776e6c6f616473)](https://packagist.org/packages/laravie/eloquent-dynamodb)[![Latest Unstable Version](https://camo.githubusercontent.com/cee766c1f82cb384167c550c0ce868f0e7e4885f44e68135c87cf46a4b6bfb5c/68747470733a2f2f706f7365722e707567782e6f72672f6c6172617669652f656c6f7175656e742d64796e616d6f64622f762f756e737461626c65)](https://packagist.org/packages/laravie/eloquent-dynamodb)[![tests](https://github.com/laravie/eloquent-dynamodb/workflows/tests/badge.svg?branch=1.x)](https://github.com/laravie/eloquent-dynamodb/actions?query=workflow%3Atests+branch%3A1.x)[![License](https://camo.githubusercontent.com/4dfa556443b2c01eb630ea7c1a363d1f1272ddf783ed3bd9315a3c910e5160f1/68747470733a2f2f706f7365722e707567782e6f72672f6c6172617669652f656c6f7175656e742d64796e616d6f64622f6c6963656e7365)](https://packagist.org/packages/laravie/eloquent-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.

- [Installation](#installation)
- [Usages](#usages)
    - [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)
- [FAQ](#faq)
- [License](LICENSE)
- [Author and Contributors](#author-and-contributors)

Installation
------------

[](#installation)

To install through composer, run the following command from terminal:

```
composer require "laravie/eloquent-dynamodb"

```

### Laravel setup

[](#laravel-setup)

Only if you disable package discovery, please add the following service provider to `config/app.php` under `providers`:

```
    // config/app.php

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

Next you may want to publish the configuration file using the following command:

```
php artisan vendor:publish --provider="Laravie\DynamoDb\DynamoDbServiceProvider"

```

> You can then update DynamoDb config in [config/dynamodb.php](config/dynamodb.php) or configurate the value using `.env`.

### Lumen setup

[](#lumen-setup)

You can either copy the configuration file manually or use [laravelista/lumen-vendor-publish](https://github.com/laravelista/lumen-vendor-publish) to install the `vendor:publish` command.

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

> You can then update DynamoDb config in [config/dynamodb.php](config/dynamodb.php) or configurate the value using `.env`.

Usages
------

[](#usages)

- Extends your model with `Laravie\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 `Laravie\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 Laravie\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.

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

32

—

LowBetter than 72% of packages

Maintenance16

Infrequent updates — may be unmaintained

Popularity26

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 64.4% 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 ~52 days

Recently: every ~85 days

Total

8

Last Release

2009d ago

PHP version history (2 changes)v1.1.0PHP &gt;=7.1

v1.3.0PHP &gt;=7.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/172966?v=4)[Mior Muhammad Zaki](/maintainers/crynobone)[@crynobone](https://github.com/crynobone)

---

Top Contributors

[![baopham](https://avatars.githubusercontent.com/u/783410?v=4)](https://github.com/baopham "baopham (242 commits)")[![crynobone](https://avatars.githubusercontent.com/u/172966?v=4)](https://github.com/crynobone "crynobone (61 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)")[![michaelshaffer37](https://avatars.githubusercontent.com/u/12464025?v=4)](https://github.com/michaelshaffer37 "michaelshaffer37 (7 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)")[![teeedwards](https://avatars.githubusercontent.com/u/117519304?v=4)](https://github.com/teeedwards "teeedwards (2 commits)")[![frank-amsterdam](https://avatars.githubusercontent.com/u/56869801?v=4)](https://github.com/frank-amsterdam "frank-amsterdam (2 commits)")[![pellaras](https://avatars.githubusercontent.com/u/14969790?v=4)](https://github.com/pellaras "pellaras (2 commits)")[![footballencarta](https://avatars.githubusercontent.com/u/1312258?v=4)](https://github.com/footballencarta "footballencarta (2 commits)")[![mlcollins10](https://avatars.githubusercontent.com/u/1544921?v=4)](https://github.com/mlcollins10 "mlcollins10 (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)")[![gchauqui-bondacom](https://avatars.githubusercontent.com/u/23453884?v=4)](https://github.com/gchauqui-bondacom "gchauqui-bondacom (1 commits)")[![guspio](https://avatars.githubusercontent.com/u/56343436?v=4)](https://github.com/guspio "guspio (1 commits)")[![JackPriceBurns](https://avatars.githubusercontent.com/u/5484580?v=4)](https://github.com/JackPriceBurns "JackPriceBurns (1 commits)")[![adrian7](https://avatars.githubusercontent.com/u/225180?v=4)](https://github.com/adrian7 "adrian7 (1 commits)")[![odiaseo](https://avatars.githubusercontent.com/u/870628?v=4)](https://github.com/odiaseo "odiaseo (1 commits)")

---

Tags

laravelawsdynamodb

### Embed Badge

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

```
[![Health](https://phpackages.com/badges/laravie-eloquent-dynamodb/health.svg)](https://phpackages.com/packages/laravie-eloquent-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)
