Menu
Amazon DynamoDB
Developer Guide (API Version 2012-08-10)

Scanning Tables and Indexes: PHP

The Scan operation reads all of the items in a table or index. To learn more about performance related to scan and query operations, see Query and Scan Operations in DynamoDB.

The following are the common steps for using the AWS SDK for PHP.

  1. Create an instance of the DynamoDB client.

  2. Provide the parameters for a DynamoDB operation, including any optional parameters.

  3. Load the response from DynamoDB into a local variable for your application.

Consider the following Reply table that stores replies for various forum threads.

Reply ( Id, ReplyDateTime, Message, PostedBy )

The table maintains all the replies for various forum threads. Therefore, the primary key is made of both the Id (partition key) and ReplyDateTime (sort key). The following PHP code snippet scans the table.

Note

This code sample assumes that you have already loaded data into DynamoDB for your account by following the instructions in the Creating Tables and Loading Sample Data section. Alternatively, you can load the data using the instructions in the Creating Example Tables and Uploading Data Using the AWS SDK for PHP topic.

For step-by-step instructions to run the following example, see PHP Code Samples.


require 'vendor/autoload.php';

$sdk = new Aws\Sdk([
    'region'   => 'us-west-2',
    'version'  => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

$response = $dynamodb->scan([
    'TableName' => 'Reply'
]);

foreach ($response['Items'] as $key => $value) {
    echo 'Id: ' . $value['Id']['S'] . "\n";
    echo 'ReplyDateTime: ' . $value['ReplyDateTime']['S'] . "\n";
    echo 'Message: ' . $value['Message']['S'] . "\n";
    echo 'PostedBy: ' . $value['PostedBy']['S'] . "\n";
    echo "\n";
}

Specifying Optional Parameters

The scan function supports several optional parameters. For example, you can optionally use a filter expression to filter the scan result. In a filter expression you specify a condition and an attribute name on which you want the condition evaluated. For more information, see Scan.

The following PHP code scans the ProductCatalog table to find items that are priced (incorrectly) at less than or equal to zero. The sample specifies the following optional parameters:

  • FilterExpression to retrieve only the items priced at less than or equal to zero.

  • ProjectionExpression to specify the attributes to retrieve for items in the query results


$response = $dynamodb->scan([
        'TableName' => 'ProductCatalog',
        'ProjectionExpression' => 'Id, Price',
        'ExpressionAttributeValues' => [
            ':val1' => ['N' => '0']] ,
        'FilterExpression' => 'Price <= :val1',
]);

foreach ($response['Items'] as $key => $value) {
   echo 'Id: ' . $value['Id']['N'] . ' Price: ' . $value['Price']['N'] . "\n";
   echo "\n";
}

You can also optionally limit the page size, the number of items per page, by adding the optional Limit parameter. Each time you execute the scan function, you get one page of results with a specified number of items. To fetch the next page you execute the scan function again by providing primary key value of the last item in the previous page so the scan function can return the next set of items. You provide this information in the request by setting the ExclusiveStartKey property. Initially this property can be null. For retrieving subsequent pages you must update this property value to the primary key of the last item in the preceding page.

The following PHP code snippet scans the ProductCatalog table. In the request it specifies the Limit and ExclusiveStartKey optional parameters.


$tableName = 'ProductCatalog';

# The Scan operation is paginated. Issue the Scan request multiple times.
do {
    echo "Scanning table $tableName\n";
    $request = [
        'TableName' => $tableName,
        'ExpressionAttributeValues' =>  [
           ':val1' => ['N' => '201']
        ],
        'FilterExpression' => 'Price < :val1',
        'Limit' => 2
    ];

    # Add the ExclusiveStartKey if we got one back in the previous response
    if(isset($response) && isset($response['LastEvaluatedKey'])) {
        $request['ExclusiveStartKey'] = $response['LastEvaluatedKey'];
    }

    $response = $dynamodb->scan($request);

    foreach ($response['Items'] as $key => $value) {
        echo 'Id: ' . $value['Id']['N'] . "\n";
        echo 'Title: ' . $value['Title']['S'] . "\n";
        echo 'Price: ' . $value['Price']['N'] . "\n";
        echo "\n";
    }

} 
# If there is no LastEvaluatedKey in the response, there are no more items matching this Scan
while(isset($response['LastEvaluatedKey'])); 

Example - Loading Data Using PHP

The following PHP code example prepares sample data to be used by subsequent examples. The program deletes and then re-creates the ProductCatalog table, then loads the table with data.

Note

For step-by-step instructions to run these code examples, see PHP Code Samples.

<?php
require 'vendor/autoload.php';

date_default_timezone_set('UTC');

use Aws\DynamoDb\Exception\DynamoDbException;

$sdk = new Aws\Sdk([
    'region'   => 'us-west-2',
    'version'  => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

$tableName = 'ProductCatalog';

// Delete an old DynamoDB table

echo "Deleting the table...\n";

try {
    $response = $dynamodb->deleteTable([
        'TableName' => $tableName
    ]);

    $dynamodb->waitUntil('TableNotExists', [
        'TableName' => $tableName,
        '@waiter' => [
            'delay'       => 5,
            'maxAttempts' => 20
        ]
    ]);
    echo "The table has been deleted.\n";

    echo "The table {$tableName} has been deleted.\n";
} catch (DynamoDbException $e) {
    echo $e->getMessage() . "\n";
    exit ("Unable to delete table $tableName\n");
}


// Create a new DynamoDB table

echo "# Creating table $tableName...\n";

try {
    $response = $dynamodb->createTable([
        'TableName' => $tableName,
        'AttributeDefinitions' => [
            [
                'AttributeName' => 'Id',
                'AttributeType' => 'N'
            ]
        ],
        'KeySchema' => [
            [
                'AttributeName' => 'Id',
                'KeyType'       => 'HASH'  //Partition key
            ]
        ],
        'ProvisionedThroughput' => [
            'ReadCapacityUnits'  => 5,
            'WriteCapacityUnits' => 6
        ]
    ]);

    $dynamodb->waitUntil('TableExists', [
         'TableName' => $tableName,
         '@waiter' => [ 
             'delay'       => 5,
             'maxAttempts' => 20
         ]   
    ]); 
    echo "Table {$tableName} has been created.\n";

} catch (DynamoDbException $e) {
    echo $e->getMessage() . "\n";
    exit ("Unable to create table $tableName\n");
}   

// Populate DynamoDB table

echo "# Populating Items to $tableName...\n";

for ($i = 1; $i <= 100; $i++) {
    $response = $dynamodb->putItem([
        'TableName' => $tableName, 
        'Item' => [
            'Id'      => [ 'N'     => "$i" ], // Primary Key
            'Title'   => [ 'S'     => "Book {$i} Title" ],
            'ISBN'    => [ 'S'     => '111-1111111111' ],
            'Price'   => [ 'N'     => "25" ],
            'Authors' => [ 'SS' => ['Author1', 'Author2']]
        ]
    ]);

    $response = $dynamodb->getItem([
        'TableName' => 'ProductCatalog',
        'Key' => [
            'Id' => [ 'N' => "$i" ]
        ]
    ]);

    echo "Item populated: {$response['Item']['Title']['S']}\n";
    sleep(1);
}

echo "{$tableName} is populated with items.\n";

?>

        

Example - Scan Using PHP

The following PHP code example performs a serial Scan on the ProductCatalog table.

Note

Before you run this program, you will need to populate the ProductTable with data. For more details, see Example - Loading Data Using PHP.

For step-by-step instructions to run these code examples, see PHP Code Samples.

<?php
require 'vendor/autoload.php';

date_default_timezone_set('UTC');

use Aws\DynamoDb\Exception\DynamoDbException;

$sdk = new Aws\Sdk([
    'region'   => 'us-west-2',
    'version'  => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

$tableName = 'ProductCatalog';
$params = [
    'TableName' => $tableName,
    'ExpressionAttributeValues' => [
        ':val1' => ['S' => 'Book']
    ],
    'FilterExpression' => 'contains (Title, :val1)',
    'Limit' => 10 
];

// Execute scan operations until the entire table is scanned
$count = 0;
do {
    $response = $dynamodb->scan ( $params );
    $items = $response->get ( 'Items' );
    $count = $count + count ( $items );
    
    // Do something with the $items
    foreach ( $items as $item ) {
        echo "Scanned item with Title \"{$item['Title']['S']}\".\n";
    }
    
    // Set parameters for next scan
    $params ['ExclusiveStartKey'] = $response ['LastEvaluatedKey'];
} while ( $params ['ExclusiveStartKey'] );

echo "{$tableName} table scanned completely. {$count} items found.\n";

?>

        

Example - Parallel Scan Using PHP

The following PHP code example demonstrates a parallel scan, running multiple Scan requests at the same time. Finally, the program prints a summary of run time statistics.

Note

Before you run this program, you will need to populate the ProductTable with data. For more details, see Example - Loading Data Using PHP.

For step-by-step instructions to run these code examples, see PHP Code Samples.

<?php
require 'vendor/autoload.php';

date_default_timezone_set('UTC');

use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\CommandPool;

$sdk = new Aws\Sdk([
    'region'   => 'us-west-2',
    'version'  => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

$tableName = 'ProductCatalog';
$totalSegments = 5;
$params = array(
    'TableName' => $tableName,
    'ExpressionAttributeValues' =>  array (
        ':val1' => array('S' => 'Book')
    ) ,
    'FilterExpression' => 'contains (Title, :val1)',
    'Limit' => 10,
    'TotalSegments' => $totalSegments
);

// Build an array of Scan commands - one for each segment
$commands = [];
for ($segment = 0; $segment < $totalSegments; $segment++) {
    $params['Segment'] = $segment;
    $commands[] = $dynamodb->getCommand('Scan',$params);
}

// Setup a command pool to run the Scan commands concurrently
// The 'fulfilled' callback will process the results from each command 
// The 'rejected' callback will tell why the command failed
$pool = new CommandPool($dynamodb,$commands,[
   'fulfilled' => function($result, $iterKey, $aggregatePromise) {
        echo "\nResults from segment $iterKey\n";

        // Do something with the items
        foreach ($result['Items'] as $item) {
            echo "Scanned item with Title \"" . $item['Title']['S'] . "\"\n";
        }
    },
    'rejected' => function ($reason, $iterKey, $aggregatePromise) {
        echo "Failed {$iterKey}: {$reason}\n";
    }
]);

$promise = $pool->promise();
$promise->wait();

?>