AWS SDK for PHP で DynamoDB する
問題
phpでDynamoDBしたいです。
答え
準備
テーブル作成: DynamoDBは、極論テーブルは1個に全部突っ込めみたいな世界なので tbl など適当な名前でもいいでしょう。単純なキーとデータの組み合わせならパーティションキーのみソートキーなしのテーブルもあり。
下のほうの例では、パーティションキー名をpkとしているが、そういうルールがあるわけではない。設計は自由。
接続ユーザー作成: IAMユーザーを作成。DynamoDBへの権限を付与。アクセスキー、シークレットアクセスキーを控えておく。
AWS SDK for PHP をインストール
- お手軽なのは aws.phar をダウンロードして
require 'aws.phar'; - composerで管理していたら
composer require aws/aws-sdk-php - composerなしなら zip版を解凍して
require 'aws-autoloader.php';
読み込む
DynamoDbClientを使って getItemやqueryするだけなら以下1行でよい。
use Aws\DynamoDb\DynamoDbClient;
必要に応じて以下など。
use Aws\DynamoDb\DynamoDbClient; use Aws\DynamoDb\Marshaler;
接続情報の管理
接続情報は以下で設定できる。
- 実行ユーザーのホームディレクトリの ~/.aws/credentials ファイル
- 環境変数 AWS_SHARED_CREDENTIALS_FILE で指定したファイル
- 環境変数で設定する AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN
- プログラム内で引数で直接
設定方法は多数ある。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html
php で環境変数を設定するなら putenv() でできる。
putenv('AWS_ACCESS_KEY_ID=AKIAI44QH8DHBEXAMPLE');
putenv('AWS_SECRET_ACCESS_KEY=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY');
DynamoDBに接続する
接続情報が ~/.aws/credentials や環境変数の設定でよかったら、credentials など省略可能。
以下ではプログラム内で引数で渡している。
<?php
require 'aws-autoloader.php';
use Aws\DynamoDb\DynamoDbClient;
$client = new DynamoDbClient([
'region' => 'ap-northeast-1',
'version' => 'latest',
'credentials' => [
'key' => $access_key,
'secret' => $secret_key,
],
'http' => [
'timeout' => 5,
],
]);
パラメータはこちらを参照
https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.AwsClient.html#___construct
'version' => 'latest' など省略でしてよさそうなものが必須項目だったりする。省略するとエラーになる。
上の例では timeout を指定したが、これは任意項目。省略可能。
DynamoDBに問い合わせる
getItem
プライマリキーなどで項目を取得
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#getitem
<?php
$result = $client->getItem([
'Key' => [
'pk' => [
'S' => 'test'
]
],
'TableName' => 'tbl'
]);
var_dump($result);
結果
object(Aws\Result)#132 (2) {
["data":"Aws\Result":private]=>
array(2) {
["Item"]=>
array(2) {
["pk"]=>
array(1) {
["S"]=>
string(4) "test"
}
["xxxx"]=>
array(1) {
["S"]=>
string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
["@metadata"]=>
array(4) {
["statusCode"]=>
int(200)
["effectiveUri"]=>
string(45) "https://dynamodb.ap-northeast-1.amazonaws.com"
["headers"]=>
以下省略
結果は $result['Item']['xxxx']['S'] などで取得できる。
Aws\Result オブジェクトなので、 $result->get('Item'); でも取得できる。
query
インデックスを使って問い合わせ
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#query
<?php
$result = $client->query([
'TableName' => 'tbl',
'IndexName' => 'xxxx-index',
'KeyConditionExpression' => 'xxxx = :xxxx',
'ExpressionAttributeValues' => [
':xxxx' => [
'S' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
],
],
'Limit' => 10,
]);
結果
object(Aws\Result)#144 (2) {
["data":"Aws\Result":private]=>
array(4) {
["Items"]=>
array(1) {
[0]=>
array(2) {
["pk"]=>
array(1) {
["S"]=>
string(4) "test"
}
["xxxx"]=>
array(1) {
["S"]=>
string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
["Count"]=>
int(1)
["ScannedCount"]=>
int(1)
["@metadata"]=>
以下省略
結果は $result['Items'][0]['xxxx']['S'] などで取得できる。
Aws\Result オブジェクトなので、 $result->get('Items'); でも取得できる。
結果が複数返ってくることもある。
scan
コストが高いので注意
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#scan
<?php
$result = $client->scan([
'TableName' => 'tbl',
'FilterExpression' => 'xxxx = :xxxx',
'ExpressionAttributeValues' => [
':h' => [
'S' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
],
],
'Limit' => 10,
]);
結果はqueryと同様。
putItem
項目を作成
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#putitem
<?php
$client->putItem([
'TableName' => 'tbl',
'Item' => [
'pk' => [
'S' => 'abcdefg'
],
'属性aaa' => [
'S' => '属性値属性値属性値属性値'
],
],
]);
プライマリキーが重複していたら作成できない。
updateItem
項目を作成(存在しなければ作成、存在すれば更新)
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#updateitem
<?php
$client->updateItem([
'TableName' => 'tbl',
'AttributeUpdates' => [
'属性名1234' => [
'Value' => [
'S' => '値値値値値値値値値値値値値値'
],
],
],
'Key' => [
'pk' => [
'S' => 'パーティションキーなんとか'
],
]
]);
プライマリキーが重複していたら更新。項目が存在しなかったら作成。
deleteItem
項目を削除
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-dynamodb-2012-08-10.html#updateitem
<?php
$client->deleteItem([
'TableName' => 'tbl',
'Key' => [
'pk' => [
'S' => $_REQUEST['s']
],
],
]);
DynamoDBのその他のメモ - 予約語
予約語が多数ある。
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
data, list, hash, user などの単語を属性名に使うと、データの保存はできるのに、queryするときに「予約語だよ」と言われてエラーになるなどやや面倒。
Invalid FilterExpression: Attribute name is a reserved keyword; reserved keyword: user
予約語のエラーを回避するには、ExpressionAttributeNames を使うなどが必要になる。
$db->scan([
'TableName' => 'tbl',
'ExpressionAttributeNames' => ['#U' => 'user'],
'FilterExpression' => '#U = :u',
'ExpressionAttributeValues' => [
':u' => ['S' => '太郎君'],
],
'Limit' => 10,
]);
DynamoDBのその他のメモ - 問い合わせのSとかNとか
問い合わせの中にみられるSとかNとかの文字は何なのかというと、データ型記述子です。
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html
S - 文字列、N - 数値、BOOL - 真偽値 … などを表しています。