Posted at

Symfony4+api-platformでデータ保存時の挙動をカスタマイズする


What is Symfony api-platform?

rest apiをSymfony4で超簡単に実装できるバンドルです。

https://api-platform.com

※ インストール方法や基本的な使い方は既存の記事があるのでそちらを見てください。

https://qiita.com/ippey_s/items/9cceec252babe8057047

https://qiita.com/tsubo/items/2cad91228b29f6f77317


Customize actions on data persist

単にデータの読み書きするだけなら、デフォルト設定のまま @ApiResource つきのエンティティを増やすだけで使えちゃうのですが、POSTされたデータをエンティティにマップしてDBに保存するだけではない、カスタムの挙動を入れたいときってあると思います。

たとえばデータ保存と同時にメール送信とかSlack投稿とか。

そういう場合にどういう実装をすればいいか調べた&実験してみました。


Create your own DataPersister

DataPersisterInterface を実装したカスタムクラスを作るだけです。



  • supports($data) でカスタムの保存処理を行いたい対象をサポートさせる


  • persist($data) に実際の保存処理を書く


  • remove($data) に実際の削除処理を書く

サンプルはこちら https://github.com/77web/api-platform-playground/blob/a1afe552bef5e28bbfa96a6d7b29be4adc3e4725/src/Persister/BookPersister.php

※ 単なるサンプルなのでTimestampableExtensionでできそうなことしかやってませんが、実際はここでいろいろな処理を足すことができます。


Define your DataPersister as Symfony service with api_platform.data_persister tag

自作のDataPersisterを api_platform.data_persister タグをつけてサービスとして定義します。

サンプルはこちら https://github.com/77web/api-platform-playground/blob/a1afe552bef5e28bbfa96a6d7b29be4adc3e4725/config/services.yaml#L29-L34

この状態で書き込みAPIを呼び出すと、単にDBにデータを保存するのみならず、カスタム処理を実行させることができます。


How does this work?

(ここからは余談です。)

api_platform.data_persister タグをつけると、自作のDataPersisterがdata_persisterとして認識され、ChainDataPersisterクラスにセットされます。

※ 参考 SymfonyのDIコンテナでタグがどのように使われるかは Symfonyで同種のクラスを大量に使うときDIで楽するテクニック(自作タグのススメ) に書いておきました

保存時に実際にどのDataPersisterを使うかは ChainDataPersisterクラス によりストラテジーパターンを使って決定されています。

単にapi-platformを使うだけでなく、仕組みにも興味のある方は見てみてください(条件分岐禁止!) :smile:

※ ちなみにどういうわけか公式のドキュメントにカスタムのDataPersister利用について記載が見当たらなかったのでソースコードを読んでアタリをつけて実験で確認しました :sweat_drops: