読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

AmazonWebServiceのDynamoDBをPHPで利用する

こんにちわ。今回のブログ担当の中村です。

今回はPHPでAWS(AmazonWebService)のDynamoDBを利用する手順を記載してみたいと思います。

DynamoDBは簡単に言うとNoSQLデータベースサービスの一種で、RDBMSとは違いリレーションやトランザクション機能がありませんが、その分高速でビッグデータを扱うのに向いていると言われています。

弊社ではRDBMSだけでなくDynamoDBも併用しています。

スマホアプリでは、アプリ側とサーバ側で通信を行う際、ジェイルブレイクなどによって通信内容を改ざんされてしまうリスクがありますが、DynamoDBを利用することで改ざんを一部防止することができます。

例)RPG系ゲームにおいて、ダンジョンを冒険して経験値やコインやアイテムを取得するような場合
サーバ側からダンジョンの情報をアプリ側に送信してダンジョンを冒険した後、サーバ側に結果を送信する際に通信内容を改ざんされてしまうと....?
⇒ありえない単位の経験値やコインを得たような通信内容が送信されてきてもサーバ側でのチェックが難しい(どこまでがセーフでどこからがアウト?)

弊社での対策)
冒険開始時にサーバ側であらかじめ結果を算出しておいてDynamoDBにユーザーIDに紐づけて保存しておき、クリア時にDynamoDBからデータを取得して反映することで、アプリ側からの送信内容を改ざんされても影響を受けない。更に、改ざんしたユーザーを特定し、ブラックリストを作成したり、BANすることも可能。

注意点)
どのモンスターが出現して何を落とすかを全て事前に確定できるゲームシステムでしかこの手法は導入できない。

他にも色々な利用法があるのでとても便利なサービスです!

では手順を説明していきます。

AWS SDK for PHPをダウンロードします。

②AWS SDK for PHPの直下にあるconfig.inc.phpにキーとシークレットキーを登録します。

※AWSのアカウントコンソール内のSecurity Credentialsに記載してあります。

CFCredentials::set(array(  
  //そのまま  
  'development' => array(  
    //キーを入力します。  
    'key' => '************************************',  
    //シークレットキーを入力します  
    'secret' => '*********************************************************',  
    //そのまま  
    'default_cache_config' => '/var/www/html/aws_cache',  
    //そのまま  
    'certificate_authority' => false  
  ),  
  '@default' => 'development'  
));  

③PHP側でAWS利用するにはAWS SDKを読み込みます。

require_once("/var/www/html/AWSSDKforPHP/sdk.class.php");

④次にDynamoDBオブジェクトを生成します。

$dynamodb = new \AmazonDynamoDB();

基本的にはこのDynamoDBオブジェクトを介して全ての操作を行います。

ではテーブルにレコードを追加してみます。

require_once("/var/www/html/AWSSDKforPHP/sdk.class.php");  
  
$dynamodb = new \AmazonDynamoDB();  
  
// テーブル名を指定する  
$table_name = 'test_table';  
  
//登録したいデータを作る(各属性=カラムに登録したい情報を配列にまとめる)  
$attributes = array();  
$attributes['user_id'] = (string)$user_id; //登録の際には属性の型に対応させる  
$attributes['exps'] = (int)$sum_exp;
$attributes['coins'] = (int)$sum_coin;
$attributes['items'] = (string)'item1,item2,item3';  

// データをDynamoに送信できる形式に整形 
$data = array(
  'PutRequest' => array(
    'Item' => $dynamodb->attributes($attributes)
  )
);

// テーブルにレコードを追加  
$response = $dynamodb->batch_write_item(array(
  'RequestItems' => array(
    $table_name => array(
      $data
    )
  )
));

では次にデータを取得してみます。

//DynamoDBからレコードを取得する$response = (object)array();  

$response = $dynamodb->get_item(array(
  'TableName' => $table_name,                   //テーブルを指定する
  'Key' => $dynamodb->attributes(array(
    'HashKeyElement' => (string)$user_id,   //主キーを指定する
  )),
  'AttributesToGet' => array(
    'exps',                                                     //取得したい属性(カラム)を指定する
    'coins',
    'items'
  ),
  'ConsistentRead' => 'true'
));
  
// 取得に成功した場合  
  
if ($response->isOK()) {

  $data['user_id'] = $user_id;  
  $data['items'] = (array)$response->body->Item->items->S; //String型はS(String)を指定して取り出す
  $data['items'] = $data['items']['0'];
  $data['coins'] = (array)$response->body->Item->coins->N; //int型はN(Number)を指定して取り出す
  $data['coins'] = $data['coins']['0'];
  $data['exps'] = (array)$response->body->Item->exps->N;
  $data['exps'] = $data['exps']['0'];

  return $data;
} 

このような形で簡単にDynamoDBのデータを操作することができます。

RDBMSでは速度的に困ることもあると思いますので、状況に応じてRDBMSとNoSQLを使い分けるとより快適な通信を実現できるかも?(笑)