SkillAgentSearch skills...

Dynamodb

AWS DynamoDB Eloquent ORM for Laravel 6+

Install / Use

/learn @renoki-co/Dynamodb
About this skill

Quality Score

0/100

Category

Operations

Supported Platforms

Universal

README

CI Latest Stable Version Total Downloads Monthly Downloads codecov StyleCI

Laravel DynamoDB

This package is a fork from the original package by Bao Pham.

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.

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)

For Lumen, try this 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

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)

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

You can use the query builder facade to build more complex queries.

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, update, save asynchronously on DynamoDb.

Supported features

find() and delete()

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

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

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', '<', 0)->get();
$model->where('count', '<=', 0)->get();
$model->whereIn('count', [0, 100])->get();
$model->whereNotIn('count', [0, 100])->get();
$model->where('count', 'between', [0, 100])->get();
$model->where('description', 'begins_with', 'foo')->get();
$model->where('description', 'contains', 'foo')->get();
$model->where('description', 'not_contains', 'foo')->get();

// Nested conditions
$model
    ->where('name', 'foo')
    ->where(function ($query) {
        return $query
            ->where('count', 10)
            ->orWhere('count', 20);
    })->get();

// Nested attributes
$model->where('nestedMap.foo', 'bar')->where('list[0]', 'baz')->get();

whereNull() and whereNotNull()

NULL and NOT_NULL only check for the attribute presence not its value being null Please see: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html

$model->whereNull('name');
$model->whereNotNull('name');

all() and first()

// Using scan operator, not too reliable since DynamoDb will only give 1MB total of data.
$model->all();

// Basically a scan but with limit of 1 item.
$model->first();

Pagination

Unfortunately, offset of how many records to skip does not make sense for DynamoDb. Instead, provide the last result of the previous query as the starting point for the next query.

Examples:

For query such as the following:

$query = $model->where('count', 10)->limit(2);
$items = $query->all();
$last = $items->last();

Take the last item of this query result as the next "offset":

$nextPage = $query->after($last)->limit(2)->all();

// or
$nextPage = $query->afterKey($items->lastKey())->limit(2)->all();

// or (for query without index condition only)
$nextPage = $query->afterKey($last->getKeys())->limit(2)->all();

update()

$model->update($attributes);

updateAsync()

// update asynchronously and wait on the promise for completion.
$model->updateAsync($attributes)->wait();

save()

$model = new Model();
// Define fillable attributes in your Model class.
$model->fillableAttr1 = 'foo';
$model->fillableAttr2 = 'foo';

// DynamoDb doesn't support incremented Id, so you need to use UUID for the primary key.
$model->id = 'de305d54-75b4-431b-adb2-eb6b9e546014';
$model->save();

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

$model->delete();

deleteAsync()

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

chunk()

$model->chunk(10, function ($records) {
    foreach ($records as $record) {
        //
    }
});

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

$model->where('name', 'foo')->firstOrFail();

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

findOrFail()

$model->findOrFail('foo');

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

refresh()

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

getItemsCount()

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

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', '<', 4);
    }

    public function scopeCountUnder($builder, $count)
    {
        return $builder->where('count', '<', $count);
    }
}

$foo = new Foo();

// Global scope will be applied
$foo->all();

// Local scope
$foo->withoutGlobalScopes()->countUnderFour()->get();

// Dynamic local scope
$foo->withoutGlobalScopes()->countUnder(6)->get();

REMOVE — Deleting Attributes From An Item

Please see: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.

View on GitHub
GitHub Stars17
CategoryOperations
Updated8mo ago
Forks2

Languages

PHP

Security Score

87/100

Audited on Jul 27, 2025

No findings