kreait/firebase-bundleで初期化したCloud Storageをleague/flysystem-bundleで使う
kreait/firebase-bundleで初期化したCloud Storage for Firebaseのクライアントをleague/flysystem-bundleから使う方法を解説します。
kreait/firebase-bundleとは
kreait/firebase-php は Firebase Admin SDK のPHP実装で、非公式ではありますがPHPの実装としてはデファクトスタンダードとなっています。
kreait/firebase-phpをSymfonyに簡単に統合するためのバンドルとして kreait/firebase-bundle があります。
league/flysystem-bundleとは
league/flysystem は、様々なファイルシステムを透過的に利用できるようにするためのPHPライブラリです。Amazon S3やGoogle Cloud Storageなど主要なマネージドサービスにも対応しています。
league/flysystemをSymfonyに簡単に統合するためのバンドルとして league/flysystem-bundle があります。
kreait/firebase-bundleの初期化手順
公式のREADME のとおりですが、以下のような手順になります。
1. サービスアカウントの秘密鍵をダウンロード
https://console.firebase.google.com/project/{プロジェクト名}/settings/serviceaccounts/adminsdk?hl=ja
にてサービスアカウントを作成し、秘密鍵のJSONファイルをダウンロードします。今回はそれをプロジェクトルートに firebase-credentials.json
として保存することにします。
# .gitignore
/firebase-credentials.json
秘匿情報なので忘れずにgitignoreしておきましょう。
2. バンドルを設定
# config/packages/firebase.yaml
kreait_firebase:
projects:
{プロジェクト識別子}:
credentials: '%kernel.project_dir%/firebase-credentials.json'
これで、kreait_firebase.{プロジェクト識別子}.storage
というサービスIDで Kreait\Firebase\Contract\Storage
の実装クラスのインスタンスを利用できるようになります。
league/flysystem-bundleの初期化手順
こちらも 公式のREADME および Cloud Storage Providersの利用方法についての公式ドキュメント に詳細が載っていますが、以下のような手順になります。
1. Google Cloud Storage用のアダプタをインストール
$ composer require league/flysystem-google-cloud-storage
2. バンドルを設定
# config/packages/flysystem.yaml
flysystem:
storages:
default.storage:
adapter: gcloud
options:
client: Google\Cloud\Storage\StorageClient # service id
bucket: '%env(FIREBASE_STORAGE_BUCKET_NAME)%'
# prefix: optional/path/prefix # 必要なら設定
# .env(.local)
FIREBASE_STORAGE_BUCKET_NAME={プロジェクト名}.appspot.com
バケット名は {プロジェクト名}.appspot.com
になります(参考)。ローカルと本番など環境ごとに異なるプロジェクトを使い分けることになるかと思いますので、具体的な値は .env
に書きましょう。
さて、
client: Google\Cloud\Storage\StorageClient # service id
いきなりこのように書いてみましたが、現状 Google\Cloud\Storage\StorageClient
というIDのサービスは定義されていません。
なので、前提として自前で Google\Cloud\Storage\StorageClient
クラスのインスタンスを(Google\Cloud\Storage\StorageClient
というサービスIDで)サービスとして定義しておく必要があります。
Google\Cloud\Storage\StorageClient
サービスを定義
3. kreait/firebase-bundleによってすでに kreait_firebase.{プロジェクト識別子}.storage
というサービスIDで Kreait\Firebase\Contract\Storage
の実装クラスのインスタンスを利用できるようになっています。
Kreait\Firebase\Contract\Storage
のコードを見てみると、getStorageClient()
というpublicメソッドで Google\Cloud\Storage\StorageClient
のインスタンスを取得できる ことが分かります。
というわけで、これで取得したインスタンスをサービスとして定義してあげればよさそうです。
このような場合には、Symfonyのサービスコンテナの factory
機能 が活用できます。
# config/services.yaml
services:
Google\Cloud\Storage\StorageClient:
factory: ['@kreait_firebase.{プロジェクト識別子}.storage', getStorageClient]
このようにすることで、kreait_firebase.{プロジェクト識別子}.storage
サービス(つまり Kreait\Firebase\Contract\Storage
の実装クラスのインスタンス)の getStorageClient()
メソッドの戻り値を Google\Cloud\Storage\StorageClient
というIDでサービスとして定義することができます。
これで無事に設定が完了しました👍
使ってみる
実際に使ってみましょう。
適当なコントローラに以下のようなコードを書いてみます。
class SomeController extends AbstractController
{
public function __construct(private FilesystemOperator $defaultStorage)
{
}
public function someAction(): Response
{
$this->defaultStorage->write('test.txt', 'test');
return new Response();
}
}
League\Flysystem\FilesystemOperator
型の $defaultStorage
をインジェクトして、ここでは write()
メソッドを使ってテキストファイルを作成しています。
league/flysystem-bundleのREADMEに記載があるとおり、この $defaultStorage
という引数名にはルールがあり、任意の引数名で受け取ることはできません。
今回は
# config/packages/flysystem.yaml
flysystem:
storages:
default.storage:
# 略
このように default.storage
というストレージ名で定義したので、これをlowerCamelCaseで表現した $defaultStorage
という引数名にバインドされています。
このコントローラを実際に実行したあと、Firebaseのコンソールを見ると以下のようにファイルが作成されていることを確認できます👍
おまけ:kreait/firebase-bundleでFirebase Authenticationを使うときのTips
Cloud Storage for Firebaseと違ってFirebase Authenticationを使うときは特にラッパーを被せたりせず直接使うのが普通だと思います。
Cloud Storage for Firebaseの場合と同様、バンドルにFirebaseの秘密鍵を設定した時点で、kreait_firebase.{プロジェクト識別子}.auth
というサービスIDで Kreait\Firebase\Contract\Auth
の実装クラスを利用できるようになっています。
が、このサービスを複数箇所で使う必要が出てきたときに、Kreait\Firebase\Contract\Auth
型でautowireしてもらえないのは非常に不便です。
そこで、services.yamlに以下の2行を追記しておきましょう。
# config/services.yaml
services:
Kreait\Firebase\Contract\Auth:
alias: kreait_firebase.{プロジェクト識別子}.auth
これで、Kreait\Firebase\Contract\Auth
型のコンストラクタ引数(等)に自動で kreait_firebase.{プロジェクト識別子}.auth
サービスがインジェクトされてとても幸せになれます。
Discussion