PEAR::HTTP_Requestで「item=a&item=b&item=c」なURLを扱う

久々にPHP関連のエントリ。

最近、フロントエンドのテンプレートをPHPで組んで、そこからバックエンドのPerlCatalyst)の内部APIを叩く、みたいなことをしてます。

複数選択可能なチェックボックスの扱いでつまづいたのでメモ。

■結論

PEAR::HTTP_Requestで「item=a&item=b&item=c」なURLを扱う時は、

$req = new HTTP_Request( $url, array('useBrackets' => false) );

とする。

■詳細

Catalystでは、

item=a&item=b&item=c

のようなQueryStringを

my @items = $c->req->params->{ item };

とリストコンテキストで受けると、パラメータを配列で取得できます。CGI.pmの時代から「配列で受けたらまとめて返す」がPerl界の標準的な形のようです。

catalyst_server.plがコンソールに出すデバッグログで見ると、こういう形で渡ってきます。

.-------------------------------------+--------------------------------------.
| Parameter                           | Value                                |
+-------------------------------------+--------------------------------------+
| item                                | a, b, c                              |
'-------------------------------------+--------------------------------------'


ところが、PHPPEAR::HTTP_RequestでこういうQueryStringを投げると、最後の値(この場合はitem=c)だけが有効になります。

item[]=a&item[]=b&item[]=c

とすることで複数の値を渡せますが、これをCatalystで受け取ると、

.-------------------------------------+--------------------------------------.
| Parameter                           | Value                                |
+-------------------------------------+--------------------------------------+
| item[0]                             | a                                    |
| item[1]                             | b                                    |
| item[2]                             | c                                    |
'-------------------------------------+--------------------------------------'

となり、別のパラメータとして扱われるので受け取る側の処理が煩雑になります。


HTTP_Requestは与えられたURLをそのまま投げるのではなく、内部でPEAR::Net_URLのインスタンスとして扱います。

Net_URLはコンストラクタの第2引数で同名パラメータに複数の値を入れる処理が変わります。

string Net_Whois (string $url, string $useBrackets)

とマニュアルには書いてありますが、$useBracketsは実際にはstringじゃなくてbooleanです。

HTTP_Requestのインスタンスを作る時に、冒頭のように

$req = new HTTP_Request( $url, array('useBrackets' => false) );

としておくと、内部でNet_URLを呼び出す時にこの設定を引き継いでくれるのでいい感じになります。

ということで解決。