Google App Engineを利用して自作ゲームのスコアを保存・取得するシステムを開発した話(PHP)

きっかけ

友人と二人でブラウザ上で動くゲームを作っていて,スコアをどこかに保存しようということになった.

Google App Engineにしようと思ったのは,所属する研究室とは別の先生にオススメされたので使った.

多分MySQLとかのデータベースを使うともっと簡単にできたかもしれないけど,key-value型のNoSQLを使う勉強,GAEを利用する勉強にはなったと思う.

実際の方法

Google Cloud Platform の利用登録

これに関してはかなり前に登録していたので忘れてしまった.

blog.apar.jp

上記のサイトが参考になると思うので載せておく.

Google Cloud SDKの取得

実はこれに数時間かけてしまった.おそらく普通に指示通り行なっていればつまずくことはなかったと思う.

これに関しても

ゼロから始める Google App Engine の使い方(2017年) | あぱーブログ

が参考になるのでここでは割愛させていただく.

本題のスコアを保存・取得するところ

準備

今回利用したのは,PHPである.開発環境にphpとcomposerが入っていなければまず取得する.

好きなディレクトリを作成し,そこでapp.yamlファイルを作成し,以下のように記述する.

application: ***** #任意のアプリケーション名
version: 1
module: default
runtime: php55
api_version: 1

threadsafe: true

handlers:
- url: /export  # スコアを保存するためのurl
  script: export.php

- url: /import  # スコアを取得するためのurl
  script: import.php

次にcomposer.jsonファイルを作成し,以下のように記述し,

{
    "require": {
        "google/cloud-datastore": "^1.0",
        "symfony/console": "^3.0",
        "google/apiclient": "^2.0"
    },
    "require-dev": {
        "phpunit/phpunit": "~4.8",
        "google/cloud-tools": "^0.6"
    },
    "autoload": {
        "psr-4": { "Google\\Cloud\\Samples\\Datastore\\Tasks\\": "src" },
        "files": ["src/functions.php"]
    }
}

composer updateと打つ. すると色々ディレクトリとファイルが増える.(深くcomposerについて理解してないので細かいことは割愛)

次にGoogle Cloud Platformのコンソールを開く.

APIとサービス→認証情報→認証情報を作成→サービスアカウントキーの作成でこの画面に遷移する

f:id:wheson:20171104135540p:plain

これで作成を押すとjsonファイルがDLできるので,そのjsonファイルを現在開発してるディレクトリに突っ込む.

スコアを保存するためのphp

app.yamlでexport.phpと指定したので,それに従ってexport.phpというファイルを作成して以下のように記述する.

<?php
# Includes the autoloader for libraries installed with composer
require __DIR__ . '/vendor/autoload.php';

# Imports the Google Cloud client library
use Google\Cloud\Datastore\DatastoreClient;

# 認証
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . __DIR__ . '{jsonファイルの指定}');

# Your Google Cloud Platform project ID
$projectId = '{プロジェクトID}';

# Instantiates a client
$datastore = new DatastoreClient([
    'projectId' => $projectId
]);

# The kind for the new entity 
# Scoreという名前の種類にしているが,別にそのデータが何なのか分かればなんでもいい
$kind = 'Score'; 

# The Cloud Datastore key for the new entity
$taskKey = $datastore->key($kind);

# POST されたデータを変数に格納
# このシステムではscoreとusernameをデータストアに保存する
$postScore = $_POST["score"];
$postUsername = $_POST["username"];

# Prepares the new entity
$task = $datastore->entity($taskKey, ['score' => $postScore, 'username' => $postUsername]);

# Saves the entity
$datastore->upsert($task);

echo 'Saved ' . $task->key() . ': ' . $task['score'] . ', ' . $task['username'] . PHP_EOL;

試しに投入するプロパティを書き換え

$task = $datastore->entity($taskKey, ['score' => 1000, 'username' => 'hoge']);
dev_appserver.py .

とコマンドを打つことでローカルでサーバを起動しhttp://localhost:8080/exportにアクセスする.

それでGoogle Cloud Platformのデータストアのエンティティを見ると,名前が自動生成されたIDでscore 1000,username hogeのエンティティが作成されていることが確認できる.

これでデータストアにデータを格納することができた.書き換えた文は元に戻しておこう.

データを取得するためのphp

データを格納するだけではただのゴミ箱である.本システムではimport.phpで取得するためのphpを作った.

import.phpというファイルを作成し以下のように記述する.

<?php
# Includes the autoloader for libraries installed with composer
require __DIR__ . '/vendor/autoload.php';

# Imports the Google Cloud client library
use Google\Cloud\Datastore\DatastoreClient;

# 認証
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . __DIR__ . '{jsonファイルの指定}');

# Your Google Cloud Platform project ID
$projectId = '{プロジェクトID}';

# Instantiates a client
$datastore = new DatastoreClient([
    'projectId' => $projectId
]);

$query = $datastore->gqlQuery('SELECT * FROM Score ORDER BY score DESC');

$result = $datastore->runQuery($query);

foreach ($result as $entity){
    $data[] = array('score' => $entity['score'], 'username' => $entity['username']);
}

echo json_encode($data);

GQLというSQLとほぼ同じ文でデータを取得することができるものを利用した.

SELECT * FROM Score ORDER BY score DESC

でScoreという種類のエンティティをscoreの降順で取得せよという意味である.

他の命令は以下のリファレンスを参考にするといい.

https://cloud.google.com/datastore/docs/reference/gql_reference

本システムではranQueryで取得した結果($result)をforeach文で$data[]に連想配列で格納している. その後,json_encodeしてechoしている.

これでデータを降順で取得できるので,後はそれを利用してランキング機能を作るなりする.

ちなみに取得する限度を決めることもできるのだが,LIMIT 10と指定してもエラーが出てどうしようもなくなったので,指定しないことにした. 何も指定しなくても最大限度が決まっているので(1000件)大変なことになることは無いだろうということで諦めた.

以上がシステムの詳細である.

感想

PHP GAE datastore」などで検索をかけても情報が出てくるが,それが思い通りに動かないということが多かった.ただデータを格納して,取得するだけなのになぜこんなにも難しいのかと嘆いていたが,とりあえずうまく動いたので良かった.

データを削除するのを作っていないのは必要がないのと,悪用されると危険かもしれないと思ったからである.

GAEを勧めてくれた先生はJava サーブレットで作っていたため,コードは見せてもらったが参考にはならなかった(ごめんなさい).

実はまだこのシステムは本番利用していないので,友人とゲームの方にも組み込むように手を加えないといけない.ゲームの方も完成すれば公開しようと考えている.

参考にさせていただいたWebサイト

PHP で Google Cloud Datastore のデータを読み書きする - koni blog

Getting started with the Google Cloud Datastore API  |  Cloud Datastore Documentation  |  Google Cloud Platform

データストアのクエリ  |  Cloud Datastore のドキュメント  |  Google Cloud Platform

Google Cloud Datastore API スタートガイド  |  Cloud Datastore のドキュメント  |  Google Cloud Platform

PHPでJSONのデータを処理する方法