1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20765 -->
4 <sect3 id="zend.controller.actionhelpers.contextswitch">
5 <title>ContextSwitch および AjaxContext</title>
8 <emphasis>ContextSwitch</emphasis> アクションヘルパーは、
9 リクエストに対してさまざまなレスポンスを返す機能を実現するためのものです。
10 <emphasis>AjaxContext</emphasis> ヘルパーは
11 <emphasis>ContextSwitch</emphasis> をより特化したもので、
12 レスポンスを XmlHttpRequests で返す機能を提供します。
16 いずれかを有効にするには、コントローラに対して
17 「どのアクションがどのコンテキストに対応するのか」
19 やってきたリクエストがそのアクションで有効なコンテキストである場合、
25 レイアウト機能が有効な場合に、それを無効にする。
30 コンテキストに応じて別のビュースクリプトを効率よく扱えるようにする。
34 コンテキストに応じて適切なレスポンスヘッダを送信する。
38 オプションで、指定したコールバックを実行して
44 たとえば、次のようなコントローラを考えてみましょう。
47 <programlisting language="php"><![CDATA[
48 class NewsController extends Zend_Controller_Action
51 * トップページは listAction() に転送します
53 public function indexAction()
55 $this->_forward('list');
61 public function listAction()
68 public function viewAction()
75 ここで、<methodname>listAction()</methodname>
76 の結果を <acronym>XML</acronym> 形式でも返せるようにしたくなったとしましょう。
78 <acronym>XML</acronym> でレスポンスを返すように指示できます。
81 <programlisting language="php"><![CDATA[
82 class NewsController extends Zend_Controller_Action
84 public function init()
86 $contextSwitch = $this->_helper->getHelper('contextSwitch');
87 $contextSwitch->addActionContext('list', 'xml')
101 レスポンスヘッダ 'Content-Type' を '<filename>text/xml</filename>' にします。
105 ビューのサフィックスを '<filename>xml.phtml</filename>' (あるいは別のサフィックスをを使っているなら
106 'xml.[your suffix]') に変更します。
111 さて、次は新しいビュースクリプト '<filename>news/list.xml.phtml</filename>'
112 を作成しましょう。これが <acronym>XML</acronym> の作成とレンダリングを行います。
116 あるリクエストがコンテキストスイッチを起動するかどうかを判断するために、
117 このヘルパーはリクエストオブジェクト内のトークンを調べます。
118 デフォルトでは 'format' というパラメータを調べることになっていますが、
120 ほとんどの場合は、リクエストに 'format' パラメータを追加するだけで
121 コンテキストスイッチを行えるということです。
126 <acronym>URL</acronym> のパラメータで指定する場合: <filename>/news/list/format/xml</filename>
127 (デフォルトのルーティング方式では、アクションに続けて任意の
128 キー/値 のペアを指定できたことを思い出しましょう)
132 <constant>GET</constant> パラメータで指定する場合: <command>/news/list?format=xml</command>
137 <emphasis>ContextSwitch</emphasis> では任意のコンテキストを指定できます。
138 つまり (もし存在するなら) サフィックスを自由に変更したり
139 送信するレスポンスヘッダを任意のものに変更したり、
140 任意のコールバックで初期化や後処理を行ったりができるということです。
143 <sect4 id="zend.controller.actionhelpers.contextswitch.contexts">
144 <title>デフォルトで使用できるコンテキスト</title>
147 <emphasis>ContextSwitch</emphasis> ヘルパーで
148 使用できるデフォルトのコンテキストは、json と xml のふたつです。
154 <emphasis><acronym>JSON</acronym></emphasis>。<acronym>JSON</acronym> コンテキストは、
155 'Content-Type' レスポンスヘッダを '<filename>application/json</filename>' に設定し、
156 ビュースクリプトのサフィックスを '<filename>json.phtml</filename>' とします。
160 しかし、デフォルトではビュースクリプトは不要です。
161 これは、すべてのビュー変数を単純にシリアライズして
162 <acronym>JSON</acronym> レスポンスを直接発行するものです。
166 自動 <acronym>JSON</acronym> シリアライズ機能を使わないようにすることもできます。
169 <programlisting language="php"><![CDATA[
170 $this->_helper->contextSwitch()->setAutoJsonSerialization(false);
176 <emphasis><acronym>XML</acronym></emphasis>。<acronym>XML</acronym> コンテキストは、
177 'Content-Type' レスポンスヘッダを '<filename>text/xml</filename>' に設定し、
178 ビュースクリプトのサフィックスを '<filename>xml.phtml</filename>' とします。
179 このコンテキスト用に、新しいビュースクリプトを作成する必要があります。
185 <sect4 id="zend.controller.actionhelpers.contextswitch.custom">
186 <title>独自のコンテキストの作成</title>
189 デフォルトのコンテキストだけでは対応しきれないこともあるでしょう。
190 たとえば結果を <acronym>YAML</acronym> で返したり、<acronym>PHP</acronym> のシリアライズ文字列で返したり、
191 あるいは <acronym>RSS</acronym> や <acronym>ATOM</acronym> フィードで返したりといったようにです。
192 <emphasis>ContextSwitch</emphasis> を使用すればそれも可能です。
196 新たなコンテキストを追加する最も簡単な方法は
197 <methodname>addContext()</methodname> メソッドを使用することです。
198 このメソッドの引数は 2 つで、コンテキストの名前と
199 設定の配列を指定します。設定には、以下のうちのひとつあるいは複数を指定します。
204 <para><emphasis>suffix</emphasis>:
205 ViewRenderer で登録されているデフォルトのビューサフィックスの
210 <para><emphasis>headers</emphasis>: ヘッダ/値
211 のペアの配列で、レスポンスとともに送信したいもの。</para>
215 <para><emphasis>callbacks</emphasis>:
216 キー 'init' や 'post' を含む配列で、それぞれ
217 コンテキストの初期化や後処理の際に使用する
218 <acronym>PHP</acronym> コールバックを指定します。</para>
220 <para>初期化コールバックは、<emphasis>ContextSwitch</emphasis> が
221 コンテキストを検出した場合に実行されます。
222 これを使用して、任意のロジックを実行できます。
223 たとえば <acronym>JSON</acronym> コンテキストでは、
225 自動 <acronym>JSON</acronym> シリアライズが有効な場合に ViewRenderer
228 <para>後処理はアクションの <methodname>postDispatch()</methodname>
229 で発生します。これを使用して、任意のロジックを実行できます。
230 たとえば <acronym>JSON</acronym> コンテキストでは、このコールバックを使用して
231 自動 <acronym>JSON</acronym> シリアライズ機能が有効か無効かを調べています。
232 有効な場合はビュー変数を <acronym>JSON</acronym> にシリアライズしてレスポンスに送信し、
233 無効な場合は ViewRenderer を再度有効にします。</para>
238 コンテキストを操作するメソッドには次のようなものがあります。
243 <methodname>addContext($context, array $spec)</methodname>:
245 そのコンテキストが既に存在する場合は例外をスローします。
249 <methodname>setContext($context, array $spec)</methodname>:
250 新しいコンテキストを追加、あるいは既存のコンテキストを上書きする。
251 <methodname>addContext()</methodname> と同じように指定します。
255 <methodname>addContexts(array $contexts)</methodname>:
256 複数のコンテキストを一度に追加する。配列 <varname>$contexts</varname>
257 は、コンテキスト/設定 のペアの配列となります。
258 既に存在するコンテキストを指定した場合は例外をスローします。
262 <methodname>setContexts(array $contexts)</methodname>:
263 新しいコンテキストを追加、あるいは既存のコンテキストを上書きする。
264 <methodname>addContexts()</methodname> と同じように指定します。
268 <methodname>hasContext($context)</methodname>:
269 そのコンテキストが存在する場合に <constant>TRUE</constant>、存在しない場合に
270 <constant>FALSE</constant> を返します。
273 <listitem><para> <methodname>getContext($context)</methodname>:
275 <methodname>addContext()</methodname> で使用する設定とあわせた配列を返します。
279 <methodname>getContexts()</methodname>: すべてのコンテキストを取得する。
280 コンテキスト/設定 のペアの配列を返します。
284 <methodname>removeContext($context)</methodname>:
285 指定した名前のコンテキストを削除する。成功した場合に <constant>TRUE</constant>、
286 そのコンテキストが見つからない場合に <constant>FALSE</constant> を返します。
290 <methodname>clearContexts()</methodname>: すべてのコンテキストを削除する。
295 <sect4 id="zend.controller.actionhelpers.contextswitch.actions">
296 <title>アクションごとのコンテキストの設定</title>
299 使用するコンテキストの設定には 2 通りの方法があります。
300 コントローラ内で手動で配列を作成する方法、
301 そして <emphasis>ContextSwitch</emphasis> のメソッドでそれを作成する方法です。
305 アクションとコンテキストの関連を追加するメソッドは
306 <methodname>addActionContext()</methodname> です。
307 このメソッドには 2 つの引数を指定します。
308 ひとつはコンテキストを追加したいアクション、
309 もうひとつはコンテキスト名あるいはコンテキスト名の配列です。
310 たとえば、次のようなコントローラクラスを考えてみましょう。
313 <programlisting language="php"><![CDATA[
314 class FooController extends Zend_Controller_Action
316 public function listAction()
320 public function viewAction()
324 public function commentsAction()
328 public function updateAction()
335 ここで、'list' アクションに <acronym>XML</acronym> コンテキストを、
336 そして 'comments' アクションに <acronym>XML</acronym> コンテキストと <acronym>JSON</acronym>
337 コンテキストを追加してみることにします。これは
338 <methodname>init()</methodname> メソッドで行います。
341 <programlisting language="php"><![CDATA[
342 class FooController extends Zend_Controller_Action
344 public function init()
346 $this->_helper->contextSwitch()
347 ->addActionContext('list', 'xml')
348 ->addActionContext('comments', array('xml', 'json'))
356 <varname>$contexts</varname> を設定することもできます。
359 <programlisting language="php"><![CDATA[
360 class FooController extends Zend_Controller_Action
362 public $contexts = array(
363 'list' => array('xml'),
364 'comments' => array('xml', 'json')
367 public function init()
369 $this->_helper->contextSwitch()->initContext();
375 このほうがオーバーヘッドが少なくなりますが、
380 コンテキストの関連付けを行うメソッドには次のようなものがあります。
386 <methodname>addActionContext($action, $context)</methodname>:
387 ひとつあるいは複数のコンテキストを、あるアクションで使用できるようにする。
388 関連付けがすでに設定されている場合は、それに追記します。
389 <varname>$context</varname> は、単一のコンテキストか
394 コンテキストとして <constant>TRUE</constant> を指定すると、
395 すべてのコンテキストをそのアクションで使用できるようにします。
399 <varname>$context</varname> に空の値を指定すると、
400 そのアクションではどのコンテキストも使用できないようにします。
405 <methodname>setActionContext($action, $context)</methodname>:
406 ひとつあるいは複数のコンテキストを、あるアクションで使用できるようにする。
407 関連付けがすでに設定されている場合は、指定したものでそれを置き換えます。
408 <varname>$context</varname> は、単一のコンテキストか
413 <methodname>addActionContexts(array $contexts)</methodname>:
414 いくつかの アクション/コンテキスト のペアを一度に追加する。
415 <varname>$contexts</varname> は、アクション/コンテキスト
416 のペアの連想配列です。これは <methodname>addActionContext()</methodname>
417 へのプロキシとなります。つまり、既に別のペアが登録されている場合は
422 <methodname>setActionContexts(array $contexts)</methodname>:
423 <methodname>addActionContexts()</methodname> と同様だが、既存の
424 アクション/コンテキスト のペアは上書きする。
428 <methodname>hasActionContext($action, $context)</methodname>:
429 特定のアクションにそのコンテキストが存在するかどうかを調べる。
433 <methodname>getActionContexts($action = null)</methodname>:
434 指定したアクションのすべてのコンテキスト、
435 あるいはすべての アクション/コンテキスト のペアを返す。
439 <methodname>removeActionContext($action, $context)</methodname>:
440 ひとつあるいは複数のコンテキストを、指定したアクションから削除する。
441 <varname>$context</varname> は、単一のコンテキストか
446 <methodname>clearActionContexts($action = null)</methodname>:
447 すべてのコンテキストを、指定したアクションから削除する。
448 あるいはすべてのアクションのすべてのコンテキストを削除する。
453 <sect4 id="zend.controller.actionhelpers.contextswitch.initcontext">
454 <title>コンテキストスイッチの初期化</title>
457 コンテキストスイッチを初期化するには、アクションコントローラで
458 <methodname>initContext()</methodname> をコールする必要があります。
461 <programlisting language="php"><![CDATA[
462 class NewsController extends Zend_Controller_Action
464 public function init()
466 $this->_helper->contextSwitch()->initContext();
472 時には、使用するコンテキストを決めてしまいたいこともあるでしょう。
473 たとえば、コンテキストスイッチが起動したときには
474 <acronym>XML</acronym> コンテキストだけを使わせたいという場合などです。
476 <methodname>initContext()</methodname> に渡します。
479 <programlisting language="php"><![CDATA[
480 $contextSwitch->initContext('xml');
484 <sect4 id="zend.controller.actionhelpers.contextswitch.misc">
489 <emphasis>ContextSwitch</emphasis> ヘルパーの挙動を変更できます。
496 <methodname>setAutoJsonSerialization($flag)</methodname>:
497 デフォルトでは、<acronym>JSON</acronym> コンテキストはビュー変数をすべてシリアライズし、
498 <acronym>JSON</acronym> 記法にしたものをレスポンスとして返します。
499 レスポンスを自分で作成したい場合はこれをオフにしなければなりません。
500 これは、<methodname>initContext()</methodname> をコールする前に行う必要があります。
503 <programlisting language="php"><![CDATA[
504 $contextSwitch->setAutoJsonSerialization(false);
505 $contextSwitch->initContext();
510 <methodname>getAutoJsonSerialization()</methodname> を使用します。
516 <methodname>setSuffix($context, $suffix,
517 $prependViewRendererSuffix)</methodname>:
518 このメソッドは、指定したコンテキストに対して
521 ViewRenderer のサフィックスの前に
522 新しいサフィックスをつけるのかどうかを指定できます。
523 このフラグはデフォルトで有効になっています。
528 ViewRenderer のサフィックスのみを使用します。
534 <methodname>addHeader($context, $header, $content)</methodname>:
535 指定したコンテキストにレスポンスヘッダを追加します。
536 <varname>$header</varname> はヘッダの名前で、
537 <varname>$content</varname> はそのヘッダに渡す値となります。
541 各コンテキストは複数のヘッダを持つことができます。
542 <methodname>addHeader()</methodname> は、
543 そのヘッダをコンテキストのヘッダスタックに追加します。
547 指定した <varname>$header</varname> がそのコンテキストに既に存在する場合は、
554 <methodname>setHeader($context, $header, $content)</methodname>:
555 <methodname>setHeader()</methodname> は
556 <methodname>addHeader()</methodname> とほぼ同じですが、
563 <methodname>addHeaders($context, array $headers)</methodname>:
564 指定したコンテキストに一度に複数のヘッダを追加します。
565 <methodname>addHeader()</methodname> へのプロキシとして動作するので、
566 そのヘッダがすでに存在する場合は例外をスローします。
567 <varname>$headers</varname> は ヘッダ/コンテキスト
574 <methodname>setHeaders($context, array $headers.)</methodname>:
575 <methodname>addHeaders()</methodname> と似ていますが、これは
576 <methodname>setHeader()</methodname> へのプロキシとして動作し、
583 <methodname>getHeader($context, $header)</methodname>:
584 指定したコンテキストのヘッダの値を取得します。
585 見つからない場合は <constant>NULL</constant> を返します。
591 <methodname>removeHeader($context, $header)</methodname>:
592 指定したコンテキストの単一のヘッダを削除します。
598 <methodname>clearHeaders($context, $header)</methodname>:
599 指定したコンテキストのすべてのヘッダを削除します。
605 <methodname>setCallback($context, $trigger, $callback)</methodname>:
606 指定したコンテキストにおける指定したトリガーのコールバックを設定します。
607 トリガーに指定できる値は 'init' あるいは 'post'
608 (それぞれ、コンテキストの初期化時と postDispatch 時を表します) です。
609 <varname>$callback</varname> は <acronym>PHP</acronym> のコールバックとして正しい形式でなければなりません。
615 <methodname>setCallbacks($context, array $callbacks)</methodname>:
616 指定したコンテキストに複数のコールバックを設定します。
617 <varname>$callbacks</varname> は トリガー/コールバック
618 のペアとなります。実際のところ、登録できるコールバックは
619 ほとんどふたつだけで、初期化用のものと後処理用のものです。
625 <methodname>getCallback($context, $trigger)</methodname>:
626 指定したコンテキストにおける指定したトリガーのコールバックを取得します。
632 <methodname>getCallbacks($context)</methodname>:
633 指定したコンテキストにおけるすべてのコールバックを取得します。
634 トリガー/コールバック のペアを返します。
640 <methodname>removeCallback($context, $trigger)</methodname>:
641 指定したコンテキストにおける指定したトリガーのコールバックを削除します。
647 <methodname>clearCallbacks($context)</methodname>:
648 指定したコンテキストにおけるすべてのコールバックを削除します。
654 <methodname>setContextParam($name)</methodname>:
655 コンテキストスイッチが要求されたかどうかを調べるための
656 リクエストパラメータを設定します。デフォルトは
657 'format' ですが、このアクセサを使用することで変更できます。
661 <methodname>getContextParam()</methodname>
668 <methodname>setAutoDisableLayout($flag)</methodname>:
669 デフォルトでは、コンテキストスイッチが発生したときには
671 レイアウト機能は通常は普通のレスポンスの時に使用するものであって
672 それ以外のコンテキストでは無意味だからです。
673 しかし、時にはレイアウト機能を使いたいこともあるでしょう
674 (新しいコンテキスト用のレイアウトがある場合など)。
675 その場合は、<methodname>setAutoDisableLayout()</methodname>
676 に <constant>FALSE</constant> を渡します。これは、
677 <methodname>initContext()</methodname> をコールするより
678 <emphasis>前に</emphasis> 行わなければなりません。
682 このフラグの現在の値を取得するには、アクセサ
683 <methodname>getAutoDisableLayout()</methodname> を使用します。
689 <methodname>getCurrentContext()</methodname> を使うと、
691 コンテキストスイッチが発生していない場合や
692 <methodname>initContext()</methodname> の起動前にコールした場合は
693 <constant>NULL</constant> を返します。
699 <sect4 id="zend.controller.actionhelpers.contextswitch.ajaxcontext">
700 <title>AjaxContext の機能</title>
703 <emphasis>AjaxContext</emphasis> ヘルパーは
704 <emphasis>ContextSwitch</emphasis> を継承したものです。
705 <emphasis>ContextSwitch</emphasis> の機能はすべて使用できます。
710 まず、コンテキストを決めるアクションコントローラのプロパティは
711 <varname>$ajaxable</varname> となります。これにより、
712 <acronym>AJAX</acronym> 用と通常の <acronym>HTTP</acronym> リクエスト用で別のコンテキストを使用できるようになります。
713 <emphasis>AjaxContext</emphasis> の *<emphasis>ActionContext()</emphasis>*
714 系のメソッドは、このプロパティに書き込みます。
718 次に、これは XmlHttpRequest が発生した場合にのみ起動します。
719 リクエストオブジェクトの <methodname>isXmlHttpRequest()</methodname>
720 メソッドで判断します。したがって、たとえコンテキストパラメータ
721 ('format') をリクエストで渡したとしても、そのリクエストが
722 XmlHttpRequest でない場合はコンテキストスイッチが発生しません。
726 3 番目に、<emphasis>AjaxContext</emphasis> は <acronym>HTML</acronym> コンテキストを追加します。
727 このコンテキストでは、サフィックスを '<filename>ajax.phtml</filename>'
728 として通常のリクエストのコンテキストと区別しています。
732 <example id="zend.controller.actionhelpers.contextswitch.ajaxcontext.example">
733 <title>Ajax リクエストに対してアクションに応答させる</title>
736 この例では、アクション 'view'、'form' および 'process'
737 に対する <acronym>AJAX</acronym> リクエストにレスポンスを返させるようにしています。
738 最初のふたつ 'view' および 'form' では、<acronym>HTML</acronym>
739 コード片を返してページを更新させます。最後の 'process'
740 については <acronym>JSON</acronym> を返しています。
743 <programlisting language="php"><![CDATA[
744 class CommentController extends Zend_Controller_Action
746 public function init()
748 $ajaxContext = $this->_helper->getHelper('AjaxContext');
749 $ajaxContext->addActionContext('view', 'html')
750 ->addActionContext('form', 'html')
751 ->addActionContext('process', 'json')
755 public function viewAction()
758 // AjaxContext の場合は comment/view.ajax.phtml
762 public function formAction()
764 // 新規コメントの追加フォームをレンダリングします
765 // AjaxContext の場合は comment/form.ajax.phtml
769 public function processAction()
772 // 結果を JSON で返します。結果をビュー変数に格納するだけで、
779 クライアント側では、<acronym>AJAX</acronym> ライブラリからエンドポイント
780 '<filename>/comment/view</filename>'、'<filename>/comment/form</filename>' そして
781 '<filename>/comment/process</filename>' へリクエストを送ることになります。
783 '<filename>/comment/view/format/html</filename>'、'<filename>/comment/form/format/html</filename>' そして
784 '<filename>/comment/process/format/json</filename>' のように指定します
785 (あるいはクエリ文字列で "?format=json" のようにしてもかまいません)。
789 ライブラリ側で 'X-Requested-With:
790 XmlHttpRequest' ヘッダが設定されていれば、
791 このアクションは適切な形式でレスポンスを返します。