FirestoreをREST APIで操作
Firestoreをプロジェクトに導入するには、通常公式ページのスタートガイド記載のクライアントライブラリをインストールします。
ただ、PHPに関してはgRPC拡張機能を別で導入したり、他の言語よりも手間がかかります。しかも、CentOS系のLinuxではC言語で書かれたソースをgit cloneしてコンパイルしないといけないという、超絶めんどくさい仕様となっています。
このため、今回LaravelからFirestoreを操作する方法として、REST APIを使ったやり方を採用しました。
PHPで書いてるプログラム部分だけ見たい方は、最後の方に記載していますので目次から飛んでください。
REST APIでFirestoreを操作する手順
REST APIで操作できるなら簡単かと思いきや、結構なハマりポイントがあります。REST操作するまでに必要な工程を記載しておきます。
- Firebaseプロジェクトのサービスアカウントを作成
- 作成したサービスアカウントからP12形式の鍵ファイルをダウンロード
- 鍵ファイルをP12からpem形式に変換
- Firestoreのルールを記載する (一番下の方に書いてます)
ここまでがブラウザ上での作業です。以下はプログラム内での工程です。
- 鍵ファイルを使ってJWTを作成
- JWTでOAuth認証しトークンを取得
- トークンを使ってREST APIを呼ぶ
これでようやくREST APIが呼べるようになります。このやり方をやってる人が少ないのか、WEB上にも情報が少なく、ドキュメントも見つけにくいので苦労しました…。
主な手順については下記公式ページに書かれています。
実際のコード例(Laravel/PHP)
JWTを作ってOAuth認証し、トークンを取得してREST APIを呼ぶまでの具体的なコードは下記です。
雑で申し訳ないですが、PHPを使ったREST API呼び出しで悩んでいる方には参考になると思います。成功するとFirestoreのcitiesコレクションの中身が取得できます。
public function test()
{
$http_client = new \GuzzleHttp\Client();
$now = time();
$header = array(
'alg' => 'RS256',
'typ' => 'JWT'
);
$claim = array(
'iss' => 'yourapp@appspot.gserviceaccount.com', //ご自分のFirebaseサービスアカウントアドレス
'scope' => 'https://www.googleapis.com/auth/datastore',
'aud' => 'https://www.googleapis.com/oauth2/v4/token',
'exp' => $now + 3600,
'iat' => $now,
);
//pem-keyファイルの読み込み
$private_key = openssl_get_privatekey('file://' . base_path() . '/key.pem', 'passphrase');
//base64エンコード
$header_base64 = base64_encode(json_encode($header));
$claim_base64 = base64_encode(json_encode($claim));
//鍵で署名
openssl_sign($header_base64 . '.' . $claim_base64, $signature, $private_key, 'sha256WithRSAEncryption');
$signature_base64 = base64_encode($signature);
//JWT作成
$jwt = $header_base64 . '.' . $claim_base64 . '.' . $signature_base64;
//JWTでOAuth認証、トークン取得
$response_token = $http_client->request(
'POST',
'https://www.googleapis.com/oauth2/v4/token',
[
'Content-Type' => 'application/x-www-form-urlencoded',
'form_params' => [
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwt,
],
]
);
$token = json_decode($response_token->getBody())->access_token;
//トークンを使ってREST API呼び出し
$response = $http_client->request(
'GET',
//ご自分のFirebaseプロジェクトID(yourapp)を指定してください, citiesコレクションをあらかじめ作成しておいてください
'https://firestore.googleapis.com/v1/projects/yourapp/databases/(default)/documents/cities',
[
'Content-Type' => 'application/x-www-form-urlencoded',
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
]
);
return $response->getBody();
}
ちなみにFirestoreのルールですが、下のように書けばトークンによる認証が有効になり、read/writeできるようになります。重要なポイントとして、トークンの有効期限は最大1時間です。
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if requests.auth.token.admin == true;
}
}
}
JWTの作成とか、REST APIの詳しいドキュメントが見たい方は、下記ページに書かれているので参考にしてください。(基本英語です)
JWTの作り方↓

REST APIリファレンス(テスト実行も可能)↓

Firestoreのトークンを使ったルール記載方法について↓

コメント