DynamoDB + CakePHP3でデータを保存してみる
はじめに
RSSリーダーだの記事解析だのいろいろやってみたい&AWSのお勉強をしてみたいツマ・ヨーコです。こんばんわ。
なるべく疎結合な設計を目指して、
- RSSフィードへのアクセス
- パースしてほげほげする
この辺は分離したくて、RSSフィードを何も考えずにぶち込む先としてDynamoDBとして採用してみました。
ただ、DynamoDB + CakePHP3でやりたいのだけれど、AWS SDK for PHPの情報が古いバージョンのものだったりして、てこずったのでメモ残します。
環境
コード
設定ファイル
/** * * AWS SDK Setting * */ 'Aws' => [ 'includes' => ['_aws'], 'services' => [ 'default_settings' => [ 'params' => [ 'version' => '2012-08-10',//dynamo DBの場合はこの日付 'region' => 'us-east-1', //利用しているリージョン 'credentials' => [ 'secret' => '<AWSコンソールから取得したもの>', 'key' => '<AWSコンソールから取得したもの>', ] ] ] ] ]
これをAPPROOT/config/app.phpに追加します。
ラッパークラス
<?php namespace App\Model\Table; //これは各自の設計思想に応じて決めてください use Cake\Core\Configure; use Aws\Sdk; use Aws\DynamoDb\DynamoDbClient; use Aws\DynamoDb\Exception\DynamoDbException; use Aws\DynamoDb\Marshaler; //Exceptionは何使うか見直した方がいいかも use \Exception; class AwsDynamoDb{ protected $_table_name = null; protected $_pk_name = null; protected $_pk_type = null; //"int" or "string" protected $_sdk = null; protected $_dynamodb = null; protected $_marshaler = null; const TYPE_NAME_INT = 'int'; const TYPE_NAME_STRING = 'string'; public function __construct(String $table_name, String $pk_name, String $pk_type){ $this->_table_name = $table_name; $this->_pk_name = $pk_name; //Dynamo DBへのリクエストJSONは、PKの型が間違ってるとエラーとなるため、 //あらかじめはじいておきたい。 if($pk_type != self::TYPE_NAME_INT && $pk_type != self::TYPE_NAME_STRING){ throw new Exception('Invalid Dynamo DB Primary Key Type Setting.'); }else{ $this->_pk_type = $pk_type; } try{ //SDKのセッティング $this->_sdk = new Sdk(Configure::read('Aws.services.default_settings.params')); //DynamoDBのセッティング $this->_dynamodb = $this->_sdk->createDynamoDb(); //Mashalerのnew。このクラスを使って、jsonをDynamoDBでいい感じに格納するオブジェクトにする。 $this->_marshaler = new Marshaler(); }catch(DynamoDbException $e1){ //とりあえず呼び出し元にぶん投げ。あとで考える。 throw $e1; }catch(Exception $e2){ //とりあえず呼び出し元にぶん投げ。あとで考える。 throw $e2; } } /** * putItemのラッパー */ public function put($pk, $body){ if(!$this->_check_pk_type($pk)) throw new Exception('Invalid Dynamo DB Primary Key Type.'); $item_array = array_merge([$this->_pk_name => $pk],$body); //文字コードについてはあとで考える $item_json = json_encode($item_array); //DynamoDBテーブル名と格納データをセット // $item = [ 'TableName' => $this->_table_name, 'Item' => $this->_marshaler->marshalJson($item_json) ]; //putItem実行 $result = $this->_dynamodb->putItem($item); } //Dynamo DBへのリクエストJSONは、PKの型が間違ってるとエラーとなるため private function _check_pk_type($pk){ if($this->_pk_type==self::TYPE_NAME_INT){ if(!is_int($pk)){ return false; } }elseif($this->_pk_type==self::TYPE_NAME_STRING){ if(!is_string($pk)){ return false; } }else{ //通常ありえない throw new Exception('Invalid Dynamo DB Primary Key Type Setting.'); } return true; } }
呼び出し方
$dynamo = new AwsDynamoDb('<AWSコンソールで作ったテーブル名>','<AWSコンソールで作ったPrimary Key>',AwsDynamoDb::TYPE_NAME_INT); $dynamo->put(10,['info'=>'aaa']);
結果
上手く入りました。
ハマったところ
設定ファイルの構造
古いSDKだと
'params' => [ 'version' => 'latest', 'region' => 'us-east-1', //利用しているリージョン 'secret' => '<AWSコンソールから取得したもの>', 'key' => '<AWSコンソールから取得したもの>', ]
こういう書き方らしく、
- secetとkeyが認識されなくて困った。credentialsの下に入れないといけないらしい。
- versionが日付じゃないとダメと怒られた
ちなみに、versionは
こちらで確認できます。DynamoDBは2012-08-10 とこのと。
Amazon DynamoDB Aws\DynamoDb\DynamoDbClient 2012-08-10
と書いてあります。
Aws/Sdkを使え
古いSDKはAws/Common/Awsクラスからクライアントを生成していたようで、参考ブログのマネしてuse Aws/Common/Awsとかしてもnot foundくらって悲しい思いをしていた。