symfony 1.1は異なるフォーマットとmime-typeのネイティブのサポート機能を導入します。
このことは同じモデルとコントローラはリクエストされたフォーマットに基づいて異なるテンプレートを持つことを意味します。
デフォルトのフォーマットはHTMLのままですが、symfonyはfactories.ymlファイルで定義されたいくつかのフォーマットをそのままサポートします:
request:
class: sfWebRequest
param:
formats:
txt: text/plain
js: [application/javascript, application/x-javascript, text/javascript]
css: text/css
json: [application/json, application/x-json]
xml: [text/xml, application/xml, application/x-xml]
rdf: application/rdf+xml
atom: application/atom+xml
それぞれのフォーマットは1つもしくは複数のmime-typeに関連づけされます。
これらのmime-typeはHTTPのAcceptヘッダーを解析することでリクエストされたフォーマットを自動的に決定するために使われます。
ブラウザーをとおしてデータを利用可能なものにしてWebサービスとして公開したい場合にこれはとても重宝します。
レスポンスのフォーマットを変更するには、下記のようにWebサービスのクライアントがAcceptヘッダーを変更することだけが必要です:
$ curl -H "Accept: application/xml" http://ws.example.com/api/article # データのXML表現を取得するため $ curl -H "Accept: application/json" http://ws.example.com/api/article # データのJSON表現を取得するため
異なるフォーマットをサポートすることは異なるテンプレートを作ることと同じぐらい簡単です。
Webサービスがapi/articleアクションによって管理されることを前提とします。
HTML、XMLとJSONフォーマットをサポートするために、apps/frontend/modules/api/templatesの中で作らなければならないテンプレートの一覧です:
- articleSuccess.php
- articleSuccess.xml.php
- articleSuccess.json.php
デフォルトでは、symfonyは、フォーマットに従ってContent-Typeレスポンスの変更を行い、HTMLではないフォーマットに対しては、レイアウトを無効にします。
パーシャルとレイアウトでさえもリクエストされたフォーマットに基づいて異なることがあります。
たとえば、listパーシャルをテンプレートの中に含める場合、ロードされたパーシャルの名前は現在のフォーマットに依存します:
- _list.php
- _list.xml.php
- _list.json.php
別の例を考えてみましょう。
スタイルシートもしくはJavaScriptファイルをすぐに作りたいとします。
これらの事例においてHTTPのAcceptヘッダーは常に当てにできないので、ルーティングルールのsf_format変数を利用することでフォーマットの種類を強制できます。
動的なスタイルシート用のルートを作る方法は次のとおりです:
css1:
url: /css/dynamic1.css
param: { module: css, action: dynamic, sf_format: css }
1つのアクションに対して複数のフォーマットを許可するためにURLパターンの中でsf_format変数を使うこともできます:
api_article:
url: /api/article.:sf_format
param: { module: api, action: article }
requirements:
sf_format: (?:html|xml|json)
たいていの場合、新しいフォーマットをサポートするためにアクションのコードを変更する必要はありません; しかしフォーマットのために何か特別なことを本当に行う必要がある場合、現在のフォーマットを取得してそれに応じてふるまうために$request->getRequestFormat()を呼び出すことができます。
Ok、お待ちかねのお話です!
iPhone用に最適化されたWebサイトを作りたい場合を考えてみましょう。
デフォルトではiphoneフォーマットは存在しませんが設定するのはかなり簡単です。
最初に、iPhoneから由来するリクエストを決定する方法が必要です。
User-AgentヘッダーがMobileとSafariの単語を含む場合、ブラウザがiPhoneであることを安全に推測できます。request.filter_parametersイベント用のリスナーを登録することでこのロジックをProjectConfigurationクラスに設置できます:
// config/ProjectConfiguration.class.php class ProjectConfiguration extends sfProjectConfiguration { public function setup() { // ... $this->dispatcher->connect('request.filter_parameters', array($this, 'filterRequestParameters')); } public function filterRequestParameters(sfEvent $event, $parameters) { $request = $event->getSubject(); if (preg_match('#Mobile/.+Safari#i', $request->getHttpHeader('User-Agent'))) { $request->setRequestFormat('iphone'); } return $parameters; } }
これで、リクエストが来るたびにfilterParameters()メソッドが呼び出され、ブラウザーがiPhoneの場合にリクエストフォーマットがiphoneに変更されます。
これでお終いです!
iPhoneから来るすべてのリクエストは*Success.phpテンプレートの代わりに*Success.iphone.phpテンプレートを使います。
iPhoneのために特別なスタイルシートもしくはJavaScriptファイルを使いたい場合(たとえばiui libraryを使う場合)、view.configure_formatをリスニングすることでビューを設定することもできます:
class ProjectConfiguration extends sfProjectConfiguration { public function setup() { // ... $this->dispatcher->connect('view.configure_format', array($this, 'configureIPhoneFormat')); } public function configureIPhoneFormat(sfEvent $event) { if ('iphone' == $event['format']) { // CSS、JavaScriptもしくは望むものを追加する } } }
symfony 1.1の新しいフォーマットのサポートのおかげで、Webサービス、APIもしくはiPhoneを開発することは簡単になりました。新しいフォーマットをサポートする機能を追加する作業は新しいテンプレートの一式を作る作業と同じくらい簡単です。
This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.