第4回 HTTP_Download クラス - ダウンロード支援ライブラリ - PEAR講座
くまっち先生のPEAR講座
Lecutures on PHP
第4回 HTTP_Download クラス - ダウンロード支援ライブラリ (その1)
HTTP_Downloadとは?
HTTP_Downloadは、データダウンロードに関する処理を簡単に実現することのできるパッケージです。データを「ダウンロードする」ためのライブラリではなく「ダウンロードさせる」ためのライブラリで、例えば指定したファイルをダウンロードさせるためには、リスト1のようなプログラムコードで実現できます。
リスト1. HTTP_Download 使用例1
require_once 'HTTP/Download.php';
$httpDownload = new HTTP_Download();
$httpDownload->setFile('example.txt');
$httpDownload->send();
またリスト2のように、テキストデータ(文字列)をファイルとしてダウンロードさせることもできます。
リスト2. HTTP_Download 使用例2
require_once 'HTTP/Download.php';
$httpDownload = new HTTP_Download();
$httpDownload->setData('テキストデータの例です。');
$httpDownload->setContentDisposition(HTTP_DOWNLOAD_ATTACHMENT,
'example.txt'
);
$httpDownload->send();
上記2例ともに、ブラウザでアクセスすると「example.txt」というファイルを保存するためのウィンドウがポップアップし、実際にダウンロードを実施することができます。使用例1の場合はexample.txtのテキストデータそのものが、使用例2の場合は「テキストデータの例です。」と書かれたテキストデータがファイルとしてダウンロードされることになります。
このようにHTTP_Downloadを利用することで簡単にデータダウンロード処理が実現できます。実際のファイルだけでなく任意のデータも指定できますので非常に実用性の高いライブラリの1つです。
コンストラクタによるセットアップ
それでは順に内部コードを見ていくことにしましょう。まずはクラスコンストラクタです。PHP4の頃から提供されているライブラリのため、リスト3のようにPHP4向けコンストラクタの記述方法 (*1) になっています。
リスト3. HTTP_Downloadコンストラクタ
function HTTP_Download($params = array())
{
$this->HTTP = &new HTTP_Header;
$this->setParams($params);
}
ここではクラスを動作させるための初期設定として、前回紹介したHTTP_Headerクラスを生成させHTTP_Downloadクラスのプロパティに格納しています。後に紹介しますが、ダウンロード処理を行う際に何らかのHTTPヘッダ情報を取り扱う場合に利用することになります。コンストラクタはクラスを生成する際必ず実行される処理内容になりますので、このようにセットアップ処理を実施するには最適のフェーズです。
ちなみに生成したHTTP_Headerクラスは、プロパティへリファレンスで代入 (先頭にアンパサンドを付与している) されています。
PHP5ではnewによるクラス(オブジェクト)の生成結果は自動的にリファレンスになりますが、PHP4ではオブジェクトのコピーになります。オブジェクト内における値の操作を行うと結果としてコピーとして生成されたオブジェクトとは内容の不一致が起きる可能性があり、また動作パフォーマンスやメモリ使用量の点でも注意が促されています。したがってPHP4上においてもオブジェクトはリファレンスで利用するほうがトラブルもなく良いため、本処理でもクラスをリファレンスで代入しています。
続いて登場するsetParamsメソッドは、前述した使用例でも登場した「setXXX」というメソッドを連続実行するための機能です。リスト4がそのコード内容です。
リスト4. setParamsメソッド
function setParams($params)
{
foreach((array) $params as $param => $value){
$method = 'set'. $param;
if (!method_exists($this, $method)) {
return PEAR::raiseError(
"Method '$method' doesn't exist.",
HTTP_DOWNLOAD_E_INVALID_PARAM
);
}
$e = call_user_func_array(array(&$this, $method), (array) $value);
if (PEAR::isError($e)) {
return $e;
}
}
return true;
}
「setXXX」メソッド群はHTTP_Downloadが動作するために必要なパラメータを設定するための機能として準備されています。(*2)
連想配列として与えられた引数をforeach構文で展開し、連想配列のキー(インデックス)の値を利用して「setXXX」(XXX部分がインデックスの値)という名称を生成します。そしてcall_user_func_array関数を使用して、作成したsetXXXを本クラス内にあるメソッドとして実行します。このとき生成した名称に相当するメソッドがクラス内に存在するかどうか、およびメソッドを正しく実行できたかどうかの確認をそれぞれで行い、適切にエラー(PEARによるエラーオブジェクト)を返すようにしています。
ここでメソッド実行にcall_user_func_array関数を利用しているのは、実行しようとするメソッドの引数の数が一定ではないからです。リスト5のようにメソッドの引数の数が異なる場合も、この関数を利用することで任意数の引数を1つの配列として扱うことができます。今回のように処理の流れを一括してまとめたいケースにも柔軟に対応できるため、覚えておきたいテクニックの1つです。
リスト5. call_user_func_array利用例
// 任意のメソッドに対して引数の数が異なるケースが…
$this->serFoo('foo');
$this->serFooBar('foo', 'bar');
$this->serFooBarBaz('foo', 'bar', 'Baz');
// call_user_func_arrayならば許容可能
$jobs = array('setFoo' => array('foo'),
'setFooBar' => array('foo', 'bar'),
'setFooBarBaz' => array('foo', 'bar', 'baz')
);
foreach ($jobs as $method => $params) {
call_user_func_array(array(&$this, $method), $params);
}
// これでも動作するが、eval関数は動作パフォーマンスに難あり
$jobs = array('setFoo' => 'foo',
'setFooBar' => 'foo, bar',
'setFooBarBaz' => 'foo, bar, baz'
);
foreach ($jobs as $method => $params) {
eval('$this->$method(' . $params . ');');
}
*1)
http://jp.php.net/manual/ja/language.oop.constructor.php
*2)
http://pear.php.net/manual/ja/package.http.http-download.setparams.php
- 1
- 2





ページのトップへ


今回のような実践的な経験がエンジニアのキャリアに繋がると思います。是非サービスを成功させて下さい!