Amazon DynamoDB (2011-12-05)

This guide focuses on the AWS SDK for PHP client for Amazon DynamoDB. This guide assumes that you have already downloaded and installed the AWS SDK for PHP. See Installation for more information on getting started.

Note: This guide is for the 2011-12-05 API version of Amazon DynamoDB. You may also be interested in the guide for the latest API version of Amazon DynamoDB.

Creating a client

First you need to create a client object using one of the following techniques.

Factory method

The easiest way to get up and running quickly is to use the Aws\DynamoDb\DynamoDbClient::factory() method and provide your credential profile (via the profile option), which identifies the set of credentials you want to use from your ~/.aws/credentials file (see Using the AWS credentials file and credential profiles).

A region parameter is required. You can find a list of available regions using the Regions and Endpoints reference.

use Aws\DynamoDb\DynamoDbClient;

$client = DynamoDbClient::factory(array(
    'profile' => '<profile in your aws credentials file>',
    'region'  => '<region name>',
    'version' => '2011-12-05'
));

You can provide your credential profile like in the preceding example, specify your access keys directly (via key and secret), or you can choose to omit any credential information if you are using AWS Identity and Access Management (IAM) roles for EC2 instances or credentials sourced from the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.

Note

The profile option and AWS credential file support is only available for version 2.6.1 of the SDK and higher. We recommend that all users update their copies of the SDK to take advantage of this feature, which is a safer way to specify credentials than explicitly providing key and secret.

Service builder

A more robust way to connect to Amazon DynamoDB is through the service builder. This allows you to specify credentials and other configuration settings in a configuration file. These settings can then be shared across all clients so that you only have to specify your settings once.

use Aws\Common\Aws;

// Create a service builder using a configuration file
$aws = Aws::factory('/path/to/my_config.json');

// Get the client from the builder by namespace
$client = $aws->get('dynamodb_20111205');

For more information about configuration files, see Configuring the SDK.

Creating tables

You must first create a table that can be used to store items. Even though Amazon DynamoDB tables do not use a fixed schema, you do need to create a schema for the table's keys. This is explained in greater detail in Amazon DynamoDB's Data Model documentation. You will also need to specify the amount of provisioned throughput that should be made available to the table.

// Create an "errors" table
$client->createTable(array(
    'TableName' => 'errors',
    'KeySchema' => array(
        'HashKeyElement' => array(
            'AttributeName' => 'id',
            'AttributeType' => 'N'
        ),
        'RangeKeyElement' => array(
            'AttributeName' => 'time',
            'AttributeType' => 'N'
        )
    ),
    'ProvisionedThroughput' => array(
        'ReadCapacityUnits'  => 10,
        'WriteCapacityUnits' => 20
    )
));

The table will now have a status of CREATING while the table is being provisioned. You can use a waiter to poll the table until it becomes ACTIVE.

// Wait until the table is created and active
$client->waitUntil('TableExists', array(
    'TableName' => 'errors'
));

A full list of the parameters available to the createTable() operation can be found in the API documentation.

Updating a table

You can also update the table after it's been created using the updateTable() method. This allows you to do things like increase or decrease your provisioned throughput capacity.

// Update the provisioned throughput capacity of the table
$client->updateTable(array(
    'TableName' => 'errors',
    'ProvisionedThroughput' => array(
        'ReadCapacityUnits'  => 15,
        'WriteCapacityUnits' => 25
    )
));

// Wait until the table is active again after updating
$client->waitUntil('TableExists', array(
    'TableName' => 'errors'
));

Describing a table

Now that the table is created, you can use the describeTable() method to get information about the table.

$result = $client->describeTable(array(
    'TableName' => 'errors'
));

// The result of an operation can be used like an array
echo $result['Table']['ItemCount'] . "\n";
//> 0

// Use the getPath() method to retrieve deeply nested array key values
echo $result->getPath('Table/ProvisionedThroughput/ReadCapacityUnits') . "\n";
//> 15

The return value of the describeTable() method is a Guzzle\Service\Resource\Model object that can be used like an array. For example, you could retrieve the number of items in a table or the amount of provisioned read throughput.

Listing tables

You can retrieve a list of all of the tables associated with a specific endpoint using the listTables() method. Each Amazon DynamoDB endpoint is entirely independent. For example, if you have two tables called "MyTable," one in US-EAST-1 and one in US-WEST-2, they are completely independent and do not share any data. The ListTables operation returns all of the table names associated with the account making the request, for the endpoint that receives the request.

$result = $client->listTables();

// TableNames contains an array of table names
foreach ($result['TableNames'] as $tableName) {
    echo $tableName . "\n";
}

Iterating over all tables

The result of a listTables() operation might be truncated. Because of this, it is usually better to use an iterator to retrieve a complete list of all of the tables owned by your account in a specific region. The iterator will automatically handle sending any necessary subsequent requests.

$iterator = $client->getIterator('ListTables');

foreach ($iterator as $tableName) {
    echo $tableName . "\n";
}

Tip

You can convert an iterator to an array using the toArray() method of the iterator.

Adding items

You can add an item to our errors table using the putItem() method of the client.

$time = time();

$result = $client->putItem(array(
    'TableName' => 'errors',
    'Item' => $client->formatAttributes(array(
        'id'      => 1201,
        'time'    => $time,
        'error'   => 'Executive overflow',
        'message' => 'no vacant areas'
    ))
));

// The result will always contain ConsumedCapacityUnits
echo $result['ConsumedCapacityUnits'] . "\n";

As you can see, the formatAttributes() method of the client can be used to more easily format the attributes of the item. Alternatively, you can provide the item attributes without using the helper method:

$result = $client->putItem(array(
    'TableName' => 'errors',
    'Item' => array(
        'id'      => array('N' => '1201'),
        'time'    => array('N' => $time),
        'error'   => array('S' => 'Executive overflow'),
        'message' => array('S' => 'no vacant areas')
    )
));

Retrieving items

You can check if the item was added correctly using the getItem() method of the client. Because Amazon DynamoDB works under an 'eventual consistency' model, we need to specify that we are performing a consistent read operation.

$result = $client->getItem(array(
    'ConsistentRead' => true,
    'TableName' => 'errors',
    'Key' => array(
        'HashKeyElement'  => array('N' => '1201'),
        'RangeKeyElement' => array('N' => $time)
    )
));

// Grab value from the result object like an array
echo $result['Item']['id']['N'] . "\n";
//> 1201
echo $result->getPath('Item/id/N') . "\n";
//> 1201
echo $result['Item']['error']['S'] . "\n";
//> Executive overflow
echo $result['Item']['message']['S'] . "\n";
//> no vacant areas

You can also retrieve items in batches of up to 100 using the BatchGetItem() method.

$tableName = 'errors';
$keys = array();

// Given that $keyValues contains a list of your hash and range keys:
//     array(array(<hash>, <range>), ...)
// Build the array for the "Keys" parameter
foreach ($keyValues as $values) {
    list($hashKeyValue, $rangeKeyValue) = $values;
    $keys[] = array(
        'HashKeyElement'  => array('N' => $hashKeyValue),
        'RangeKeyElement' => array('N' => $rangeKeyValue)
    );
}

// Get multiple items by key in a BatchGetItem request
$result = $client->batchGetItem(array(
    'RequestItems' => array(
        $tableName => array(
            'Keys'           => $keys,
            'ConsistentRead' => true
        )
    )
));
$items = $result->getPath("Responses/{$tableName}");

Query and scan

Once data is in an Amazon DynamoDB table, you have two APIs for searching the data: Query and Scan.

Query

A query operation searches only primary key attribute values and supports a subset of comparison operators on key attribute values to refine the search process. A query returns all of the item data for the matching primary keys (all of each item's attributes) up to 1MB of data per query operation.

Let's say we want a list of all "1201" errors that occurred in the last 15 minutes. We could issue a single query that will search by the primary key of the table and retrieve up to 1MB of the items. However, a better approach is to use the query iterator to retrieve the entire list of all items matching the query.

$iterator = $client->getIterator('Query', array(
    'TableName'         => 'errors',
    'HashKeyValue'      => array('N' => '1201'),
    'RangeKeyCondition' => array(
        'AttributeValueList' => array(
            array('N' => strtotime("-15 minutes"))
        ),
        'ComparisonOperator' => 'GT'
    )
));

// Each item will contain the attributes we added
foreach ($iterator as $item) {
    // Grab the time number value
    echo $item['time']['N'] . "\n";
    // Grab the error string value
    echo $item['error']['S'] . "\n";
}

Scan

A scan operation scans the entire table. You can specify filters to apply to the results to refine the values returned to you, after the complete scan. Amazon DynamoDB puts a 1MB limit on the scan (the limit applies before the results are filtered).

A scan can be useful for more complex searches. For example, we can retrieve all of the errors in the last 15 minutes that contain the word "overflow":

$iterator = $client->getIterator('Scan', array(
    'TableName' => 'errors',
    'ScanFilter' => array(
        'error' => array(
            'AttributeValueList' => array(array('S' => 'overflow')),
            'ComparisonOperator' => 'CONTAINS'
        ),
        'time' => array(
            'AttributeValueList' => array(
                array('N' => strtotime('-15 minutes'))
            ),
            'ComparisonOperator' => 'GT'
        )
    )
));

// Each item will contain the attributes we added
foreach ($iterator as $item) {
    // Grab the time number value
    echo $item['time']['N'] . "\n";
    // Grab the error string value
    echo $item['error']['S'] . "\n";
}

Deleting a table

Warning

Deleting a table will also permanently delete all of its contents.

Now that you've taken a quick tour of the PHP client for Amazon DynamoDB, you will want to clean up by deleting the resources you created.

$client->deleteTable(array(
    'TableName' => 'errors'
));

$client->waitUntil('TableNotExists', array(
    'TableName' => 'errors'
));

Using the WriteRequestBatch

You can use the WriteRequestBatch if you need to write or delete many items as quickly as possible. The WriteRequestBatch provides a high level of performance because it converts what would normally be a separate HTTP request for each operation into HTTP requests containing up to 25 comparable requests per transaction.

If you have a large array of items you wish to add to your table, you could iterate over the them, add each item to the batch object. After all the items are added call flush(). The batch object will automatically flush the batch and write items to Amazon DynamoDB after hitting a customizable threshold. A final call to the batch object's flush() method is necessary to transfer any remaining items in the queue.

$tableName = 'batch-write-test'; // This table has a HashKey named "id"
$itemIds = array();

// Put 55 items into the table
$putBatch = WriteRequestBatch::factory($client);
for ($i = 0; $i < 55; $i++) {
    $itemIds[] = $itemId = uniqid();
    $item = Item::fromArray(array(
        'id'        => $itemId,
        'timestamp' => time(),
    ));
    $putBatch->add(new PutRequest($item, $tableName));
}
$putBatch->flush();

You can also use the WriteRequestBatch object to delete items in batches.

// Remove items from the table
$deleteBatch = WriteRequestBatch::factory($client);
foreach ($itemIds as $itemId) {
    $key = array('HashKeyElement' => array('S' => $itemId));
    $deleteBatch->add(new DeleteRequest($key, $tableName));
}
$deleteBatch->flush();

The WriteRequestBatch, PutRequest, and DeleteRequest classes are all a part of the Aws\DynamoDb\Model\BatchRequest namespace.

API Reference

Please see the Amazon DynamoDB Client API reference for a details about all of the available methods, including descriptions of the inputs and outputs.

BatchGetItem BatchWriteItem
CreateTable DeleteItem
DeleteTable DescribeTable
GetItem ListTables
PutItem Query
Scan UpdateItem
UpdateTable