はじめに
リソースは表現(Representation)のためのリソースレンダラーを持っています。
文字列評価されるとリソースはリソースレンダラーに表現されてレスポンスになります(文末[※1])。
通常はアプリケーションコンテキスト([※2]) の単位でデフォルトのレンダラーを選びますが(例:app
コンテキストでは JSONレンダラー
を使う、など)、リソース単位でレンダラーを変更することもできます。
たとえば oEmbed のような埋め込みHTMLを返すWebAPIを開発しているとしたら、JSONレスポンスの一部の値だけはHTMLテンプレートで返したいというケースもあるでしょう。
リソース単位でレンダラーを変更する
単純な例で考えます。APIで下記のJSONレスポンスを返したいとします。
{"html":"<html><h1>this is embed. bar<\/h1><\/html>"}
デフォルトのままでは下記のようにすべてがJSONになってしまいます。
"html" キーの値だけTwigテンプレートでレンダリングされたHTMLビューに変えます。
サンプルプロジェクト
kumamidori/ExampleChangeRenderer
クラス図
実装
埋め込みHTMLリソースの RenderInterface
(名前 "html") に TwigRenderer
をバインド
class Embed extends ResourceObject
{
/**
* @Inject
* @Named("html")
*/
public function setRenderer(RenderInterface $renderer)
{
return parent::setRenderer($renderer);
}
public function onGet()
{
//・・・
}
}
APIリソースで埋め込みHTMLリソースを文字列評価
namespace Kumamidori\ExampleChangeRenderer\Resource\Page\Api;
//・・・
class Example extends ResourceObject
{
//・・・
public function onGet()
{
$embed = $this->resource->get->uri('page://self/embed')->eager->request();
$this['html'] = (string) $embed; // < 文字列評価する
return $this;
}
}
補足: レンダラーによる文字列評価のタイミングの違い
- (string) 評価をすればレンダラーでレンダリングされる
- (string) 評価をしない場合に、TwigRenderer と JsonRenderer で評価が異なる
- TwigRenderer の場合:
各要素を文字列評価しようとするので__toString()
が呼ばれてそれぞれインジェクトされたレンダラーでレンダリングされる - JsonRenderer の場合: JsonSerializable インターフェイスで実装されたjsonSerializeメソッドが呼ばれてJSONになるので明示的に (string) で文字列評価しなければならない(ref. https://github.com/bearsunday/BEAR.Resource/blob/1.x/src/ResourceObject.php#L207) ([※3])
おわりに
- 当初自分では分からなくて BEAR の Issue / gitter で教えて頂きました。ありがとうございます。
参照リンク
- [※1] リソース指向パターン - BEAR 公式マニュアル
- [※2] アプリケーション - BEAR 公式マニュアル
- [※3] Gitter - BEAR.Sunday
- アプリケーションコンテキスト - Qiita
- リクエストとトランスファー -Qiita
- Issue #104
- polidog/Polidog.Todo (テスト実装やCI設定を参照させて頂きました。Thanks!)