<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 24827 -->
<sect1 id="zend.controller.request">
    <title>リクエストオブジェクト</title>
    <sect2 id="zend.controller.request.introduction">
        <title>導入</title>
        <para>
            リクエストオブジェクトとは <classname>Zend_Controller_Front</classname> とルータ、
            ディスパッチャそしてコントローラクラスの間でやり取りされる単純なバリューオブジェクトです。
            これはコントローラ、アクションそして環境 (<acronym>HTTP</acronym>、<acronym>CLI</acronym>、<acronym>PHP</acronym>-GTK など)
            に応じたその他のパラメータの内容をまとめたものです。
        </para>

        <itemizedlist>
            <listitem><para>
                モジュール名にアクセスするには
                <methodname>getModuleName()</methodname> および
                <methodname>setModuleName()</methodname> を使用します。
            </para></listitem>

            <listitem><para>
                コントローラ名にアクセスするには
                <methodname>getControllerName()</methodname> および
                <methodname>setControllerName()</methodname> を使用します。
            </para></listitem>

            <listitem><para>
                コントローラ内でコールするアクションの名前にアクセスするには
                <methodname>getActionName()</methodname> および
                <methodname>setActionName()</methodname> を使用します。
            </para></listitem>

            <listitem><para>
                アクションからアクセスできるパラメータは
                キー/値 の組み合わせの連想配列となります。これらを取得するには
                <methodname>getParams()</methodname> を、そして設定するには
                <methodname>setParams()</methodname> を使用します。各パラメータを個別に扱うには
                <methodname>getParam()</methodname> および <methodname>setParam()</methodname> を使用します。
            </para></listitem>
        </itemizedlist>

        <para>
            リクエストの型によっては、その他のメソッドが使用できることもあります。
            たとえば、デフォルトのリクエストで使用する
            <classname>Zend_Controller_Request_Http</classname> の場合は、
            リクエストされた <acronym>URI</acronym> やパス情報、
            <varname>$_GET</varname> パラメータや <varname>$_POST</varname>
            パラメータを取得するメソッドが使用可能となります。
        </para>

        <para>
            リクエストオブジェクトはフロントコントローラに渡されます。
            もしリクエストオブジェクトがなかった場合は、
            ディスパッチ処理の最初 (ルーティングが発生する前)
            にインスタンスが作成されます。これは、
            ディスパッチチェインのすべてのオブジェクトに渡されていきます。
        </para>

        <para>
            さらに、リクエストオブジェクトはテストの際にも有用です。
            開発者がリクエストを作成し、コントローラやアクション、
            パラメータや <acronym>URI</acronym> などを指定してそれをフロントコントローラに渡すことで、
            アプリケーションの流れをテストできます。
            <link linkend="zend.controller.response">レスポンスオブジェクト</link>
            と組み合わせて使用すると、
            <acronym>MVC</acronym> アプリケーションの精密で正確な単体テストが可能となります。
        </para>
    </sect2>

    <sect2 id="zend.controller.request.http">
        <title>HTTP リクエスト</title>

        <sect3 id="zend.controller.request.http.dataacess">
            <title>リクエストデータへのアクセス</title>

            <para>
                <classname>Zend_Controller_Request_Http</classname> は、関連する値へのアクセスをカプセル化します。
                たとえばコントローラやアクションルータの変数のキー名や値、
                <acronym>URI</acronym> からパースした追加のパラメータの値などにアクセスできます。
                <classname>Zend_Controller_Request_Http</classname> のプロキシとして動作することで、
                スーパーグローバルの値にパブリックメンバとしてアクセスしたり、
                現在のベース <acronym>URL</acronym> やリクエスト <acronym>URI</acronym> を管理することもできます。
                スーパーグローバルの値はリクエストオブジェクトに設定することはできません。
                そのかわりに <methodname>setParam()</methodname> および <methodname>getParam()</methodname> メソッドを使用して、
                パラメータを設定あるいは取得します。
            </para>

            <note>
                <title>スーバーグローバルデータ</title>
                <para>
                    <classname>Zend_Controller_Request_Http</classname> のパブリックプロパティを使用して
                    スーパーグローバルデータにアクセスする際に注意すべき点は、
                    プロパティ名 (スーバーグローバル配列のキー)
                    は以下の優先順位でマッチするということです。
                    1. <constant>GET</constant>, 2. <constant>POST</constant>, 3. <constant>COOKIE</constant>,
                    4. <constant>SERVER</constant>, 5. <constant>ENV</constant>.
                </para>
            </note>

            <para>
                特定のスーパーグローバルにアクセスするには、
                パブリックメソッドを使用する方法もあります。たとえば、
                <varname>$_POST['user']</varname> の値を取得するには、リクエストオブジェクト上で
                <methodname>getPost('user')</methodname> をコールします。同様に、
                <varname>$_GET</varname> 要素の場合は <methodname>getQuery()</methodname>、
                リクエストヘッダの場合は <methodname>getHeader()</methodname>
                を使用します。
            </para>

            <note>
                <title>GET および POST データ</title>
                <para>
                    リクエストオブジェクトのデータを扱う際には注意しましょう。
                    これらのデータは、一切フィルタリングを行っていません。
                    ルータやディスパッチャのほうで適切な検証とフィルタリングを行うので、
                    リクエストオブジェクト内のデータはそのままにしておきましょう。
                </para>
            </note>

            <note>
                <title>生の POST データの取得</title>

                <para>
                    1.5.0 以降では、生の投稿データを
                    <methodname>getRawBody()</methodname> メソッドで取得できます。
                    このメソッドは、データが送信されていない場合は <constant>FALSE</constant> を返します。
                    送信されている場合は、投稿内容の本文全体を返します。
                </para>

                <para>
                    これは、RESTful な <acronym>MVC</acronym>
                    アプリケーションを開発するにあたって非常に有用です。
                </para>
            </note>

            <para>
                ユーザパラメータをリクエストオブジェクトに設定するには
                <methodname>setParam()</methodname> を、後でそれを取得するには
                <methodname>getParam()</methodname> を使用します。
                ルータは、リクエスト <acronym>URI</acronym> にマッチしたパラメータを
                リクエストオブジェクトに設定する際にこの機能を使用します。
            </para>

            <note>
                <title>getParam() でのユーザパラメータ以外の取得</title>

                <para>
                    <methodname>getParam()</methodname> は、実際にはユーザパラメータ以外のところからも情報を取得しています。
                    優先順位の高い順に並べると、まず最初は <methodname>setParam()</methodname>
                    で設定したパラメータ、それから <constant>GET</constant> パラメータ、
                    <constant>POST</constant> パラメータの順になります。
                    このメソッドを使用する際には、この点に注意しましょう。
                </para>

                <para>
                    <methodname>setParam()</methodname> で設定したパラメータからだけ取得したい場合は、
                    <methodname>getUserParam()</methodname> を使用します。
                </para>

                <para>
                    さらに、1.5.0 以降では
                    どのパラメータから検索するかを制限できます。
                    <methodname>setParamSources()</methodname> に空の配列あるいは
                    値 '_GET' や '_POST' を含む配列を指定して使用します
                    (デフォルトでは両方が指定されています)。'_GET'
                    からのみに制限したい場合は
                    <methodname>setParamSources(array('_GET'))</methodname> とします。
                </para>
            </note>

            <note>
                <title>Apache のおかしな挙動</title>
                <para>
                    Apache の 404 ハンドラを使用して
                    リクエストをフロントコントローラに渡したり、
                    PT フラグを rewrite ルールで使用したりする場合は、
                    必要な <acronym>URI</acronym> 情報が含まれるのが
                    <varname>$_SERVER['REQUEST_URI']</varname>
                    ではなく <varname>$_SERVER['REDIRECT_URL']</varname>
                    であることに注意しましょう。
                    この設定を使用して無効なルーティングを取得したい場合は、
                    デフォルトの <acronym>HTTP</acronym> クラスではなく
                    <classname>Zend_Controller_Request_Apache404</classname>
                    クラスを使用してリクエストオブジェクトを作成しなければなりません。
                </para>

                <programlisting language="php"><![CDATA[
$request = new Zend_Controller_Request_Apache404();
$front->setRequest($request);
]]></programlisting>

                <para>
                    このクラスは
                    <classname>Zend_Controller_Request_Http</classname>
                    クラスを継承したもので、リクエスト <acronym>URI</acronym>
                    を自動で検出できるように変更しています。
                    これは、単純にもとのクラスと差し替えて使用できます。
                </para>
            </note>
        </sect3>

        <sect3 id="zend.controller.request.http.baseurl">
            <title>ベース URL およびサブディレクトリ</title>

            <para>
                <classname>Zend_Controller_Request_Http</classname> は、
                サブディレクトリで <classname>Zend_Controller_Router_Rewrite</classname> を使用できます。
                <classname>Zend_Controller_Request_Http</classname> は自動的にベース <acronym>URL</acronym> を検出し、
                それを適切に設定します。
            </para>

            <para>
                たとえば、<filename>index.php</filename> をウェブサーバのサブディレクトリ
                <filename>/projects/myapp/index.php</filename> においた場合は、ベース <acronym>URL</acronym>
                (rewrite base) は <filename>/projects/myapp</filename> にしなければなりません。
                マッチするルートを見つける前に、この文字列がパスの先頭から取り除かれます。
                これにより、すべてのルートに余計な文字を追加する必要がなくなります。
                ルート <command>'user/:username'</command> は、
                <filename>http://localhost/projects/myapp/user/martel</filename> および
                <filename>http://example.com/user/martel</filename> の両方にマッチするようになります。
            </para>

            <note>
                <title>URL の検出は大文字小文字を区別します</title>
                <para>
                    自動的なベース <acronym>URL</acronym> の検出処理は大文字小文字を区別します。そのため、
                    <acronym>URL</acronym> とファイルシステムのサブディレクトリ名が確実に一致する必要があります
                    (たとえ Windows マシンであっても同様です)。大文字小文字が一致しなかった場合は、
                    例外が発生します。
                </para>
            </note>

            <para>
                ベース <acronym>URL</acronym> の検出に失敗する場合は、
                <classname>Zend_Controller_Request_Http</classname> クラス、あるいは
                <classname>Zend_Controller_Front</classname> クラスの
                <methodname>setBaseUrl()</methodname> メソッドを使用して
                ベースパスを上書き指定できます。
                一番簡単な方法は <classname>Zend_Controller_Front</classname> で設定することです。
                この設定はリクエストオブジェクトに引き継がれます。
                独自のベース <acronym>URL</acronym> を設定する例を示します。
            </para>

            <programlisting language="php"><![CDATA[
/**
 * Zend_Controller_Front で独自のベース URL を指定することによるリクエストのディスパッチ
 */
$router     = new Zend_Controller_Router_Rewrite();
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('./application/controllers')
           ->setRouter($router)
           ->setBaseUrl('/projects/myapp'); // ベース URL を指定します!
$response   = $controller->dispatch();
]]></programlisting>

            <!-- TODO : to be translated -->
            <note>
                <title>Fully-Qualified URL is not supported</title>
                <para>
                    Passing a fully-qualified URL (ie: http://example.com/) to the
                    <methodname>setBaseUrl</methodname> method is not supported, and 
                    will cause issues for both the usage describe above and when using
                    the URL view helper. See ticket 
                    <ulink url="http://framework.zend.com/issues/browse/ZF-10923">
                        ZF-10923
                    </ulink> for more details.
                </para>
            </note>

        </sect3>

        <sect3 id="zend.controller.request.http.method">
            <title>リクエストメソッドの判定</title>

            <para>
                <methodname>getMethod()</methodname> では、
                現在のリソースへのリクエストの際に使用した
                <acronym>HTTP</acronym> メソッドを判定できます。
                さらに、指定した型のリクエストであったかどうかを判定するための
                メソッドも用意されています。
            </para>

            <itemizedlist>
                <listitem><para><methodname>isGet()</methodname></para></listitem>
                <listitem><para><methodname>isPost()</methodname></para></listitem>
                <listitem><para><methodname>isPut()</methodname></para></listitem>
                <listitem><para><methodname>isDelete()</methodname></para></listitem>
                <listitem><para><methodname>isHead()</methodname></para></listitem>
                <listitem><para><methodname>isOptions()</methodname></para></listitem>
            </itemizedlist>

            <para>
                これらの主な使用法は、RESTfult な
                <acronym>MVC</acronym> アーキテクチャを作成することです。
            </para>
        </sect3>

        <sect3 id="zend.controller.request.http.ajax">
            <title>AJAX リクエストの検出</title>

            <para>
                <classname>Zend_Controller_Request_Http</classname> には、
                <acronym>AJAX</acronym> リクエストを検出するための基本的なメソッド
                <methodname>isXmlHttpRequest()</methodname> が用意されています。
                このメソッドは、<acronym>HTTP</acronym> リクエストヘッダ
                <emphasis>X-Requested-With</emphasis> に
                'XMLHttpRequest' という値が設定されているかどうかを調べ、
                設定されている場合に <constant>TRUE</constant> を返します。
            </para>

            <para>
                現時点では、次の JS ライブラリがデフォルトでこのヘッダを渡すようです。
            </para>

            <itemizedlist>
                <listitem><para>Prototype/Scriptaculous (その他
                        Prototype 系のライブラリ)</para></listitem>
                <listitem><para>Yahoo! UI Library</para></listitem>
                <listitem><para>jQuery</para></listitem>
                <listitem><para>MochiKit</para></listitem>
            </itemizedlist>

            <para>
                大半の <acronym>AJAX</acronym> ライブラリは、独自の <acronym>HTTP</acronym> リクエストヘッダを送信できます。
                ご利用のライブラリがこのヘッダを送信していない場合は、
                自分でこのヘッダを追加することで
                <methodname>isXmlHttpRequest()</methodname> メソッドの動作を期待通りにできます。
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.controller.request.subclassing">
        <title>リクエストオブジェクトのサブクラスの作成</title>

        <para>
            すべてのリクエストオブジェクトクラスは、抽象クラス
            <classname>Zend_Controller_Request_Abstract</classname> を継承しています。
            このクラスでは、次のようなメソッドを定義しています。
        </para>

        <programlisting language="php"><![CDATA[
abstract class Zend_Controller_Request_Abstract
{
    /**
     * @return string
     */
    public function getControllerName();

    /**
     * @param string $value
     * @return self
     */
    public function setControllerName($value);

    /**
     * @return string
     */
    public function getActionName();

    /**
     * @param string $value
     * @return self
     */
    public function setActionName($value);

    /**
     * @return string
     */
    public function getControllerKey();

    /**
     * @param string $key
     * @return self
     */
    public function setControllerKey($key);

    /**
     * @return string
     */
    public function getActionKey();

    /**
     * @param string $key
     * @return self
     */
    public function setActionKey($key);

    /**
     * @param string $key
     * @return mixed
     */
    public function getParam($key);

    /**
     * @param string $key
     * @param mixed $value
     * @return self
     */
    public function setParam($key, $value);

    /**
     * @return array
     */
     public function getParams();

    /**
     * @param array $array
     * @return self
     */
    public function setParams(array $array);

    /**
     * @param boolean $flag
     * @return self
     */
    public function setDispatched($flag = true);

    /**
     * @return boolean
     */
    public function isDispatched();
}
]]></programlisting>

        <para>
            リクエストオブジェクトは、リクエスト環境のコンテナとなります。
            コントローラチェインが知っておくべきことは、
            コントローラやアクション、オプションパラメータ、ディスパッチ状況
            を取得したり設定したりする方法だけです。
            デフォルトでは、リクエストオブジェクトが
            コントローラおよびアクションを決定する際には
            キー controller あるいは action を使用します。
        </para>

        <para>
            このクラスかその派生クラスのいずれかを継承したクラスを作成することで、
            上で説明した作業を独自のものに変更したクラスを作成できます。
            例としては、たとえば <link linkend="zend.controller.request.http"><acronym>HTTP</acronym>
            環境用</link> のクラスや <acronym>CLI</acronym> 環境用、<acronym>PHP</acronym>-GTK 環境用のクラスがあります。
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
