Webアプリ用のアダプタ(プッシュ型)
上で説明したZend_ProgressBar_Adapter_JsPushクラスは更新時(updateメソッドが呼ばれた時)と終了時(finishメソッドが呼ばれた時)にクライアントにデータを送信しますが、クライアント側のデータを処理するJavaScriptの関数は変更することができます。
メソッド名 | 引数 | 説明 |
setUpdateMethodName | $methodName | 更新の通知を受け取るJavaScript側の関数を指定。デフォルトではZend_ProgressBar_Update。 |
setFinishMethodName | $methodName | 処理終了の通知を受け取るJavaScript側の関数を指定。デフォルトではなし。 |
特に、何も指定しない状態では終了を受け取る関数は指定されていないため、処理の終了時に何かしたい場合にはsetFinishMethodNameメソッドで指定する必要があります。
Webアプリ用のアダプタ(プル型)
Zend_ProgressBar_Adapter_JsPullクラスもWebアプリ用のクラスです。こちらはプル型のサービスを作成するためのアダプタで、クライエントからのリクエストに対してJSON形式で進捗を送信するために利用します。
プル型はプッシュ型と比べ、次のような違いがあります:
- 送信するデータは純粋なJSON形式。
- データにfinishedという項目が追加されており、値は更新時(updateメソッドやnextメソッド)にはfalseで終了時(finishメソッド)にはtrueに設定。
- ディフォルトではデータを送信した後に、PHPの処理を終了。
それでは、典型的なプル型の処理の流れを見ていきましょう:
- クライエントのJavaScriptなどが、リクエストをサーバに送信
- サーバで進捗の確認と、クライエントへの進捗の送信
- クライエントで進捗の表示
ここではXMLHttpRequestを利用してリクエストの作成し、それをZend_ProgressBarが受けて処理するサンプルを見ていきましょう。このサンプルではフォーム内のボタンを押すたびに進捗が更新されるようになっています(なお、このサンプルはInternet Explorer 5以降で動作します)。
まずはリクエストの作成です。
<script type="text/javascript"> <!-- function get_progress() { //(1)リクエストオブジェクトの作成 var http_obj = new ActiveXObject("Msxml2.XMLHTTP"); // 結果を受け取った際の処理の登録 http_obj.onreadystatechange = function() { if (http_obj.readyState == 4) { update(http_obj); //関数 update が最終的な処理を行う } }; //(2)リクエストの実行 http_obj.open("GET", "<?php echo $this->url(array('controller' => 'index', 'action'=>'pullprogress', 'session_name'=>'test1'))?>", true); http_obj.send(null); } ... <form> ... <!-- (3)クリックされたら更新 --> <input id="update" type="button" value="update progress" onClick="get_progress()"> </form>
(3)にあるフォームのボタンがクリックされるとJavaScriptのget_progress関数が呼び出されます。このget_progress関数の中では、(1)リクエストのためのオブジェクトが準備され、(2)リクエストが実際に行われます。
(1)では、リクエストの結果をupdate関数で処理することを登録しています。また、(2)ではリクエストを送信する先として「indexコントローラのpullprogressアクション」を指定しており、その際にパラメータとして「session_nameをtest1」を追加しています。
このリクエストの処理を行うのが次のpullprogressアクションです。
public function pullprogressAction() { /* 必要なコンポーネントの読み込み */ require_once('Zend/ProgressBar.php'); require_once('Zend/ProgressBar/Adapter/JsPull.php'); /* (4)セッション名を引数から取得 */ $request = $this->getRequest(); $session_name = $request->getUserParam('session_name'); /* アダプタの作成 */ $adapter = new Zend_ProgressBar_Adapter_JsPull(); /* (5)本体の作成 */ $progressbar = new Zend_ProgressBar($adapter, 0, 10, $session_name); /* (6)next や update が呼ばれた後、ディフォルトでは 処理が終了する。もし、その後に処理を続けたい場合には 次のsetExitAfterFinishedメソッドを利用する。 $progressbar->setExitAfterFinished(false); */ /* 本来はここで進捗の計算 */ /* (7)進捗の更新や通知 */ $progressbar->next(); }
プル型の場合は、リクエストが行われるたびにZend_ProgressBarオブジェクトが作成し直されます。そのため、どの処理の進捗を管理しているZend_ProgressBarオブジェクトを利用したいのかを、コントラクタで指定する必要があります。セッション名は(4)でパラメータから取得され、(5)でコンストラクタの第4引数として渡されています。
通常のアプリケーションでは、その後に進捗が計算され(7)で更新と通知が行われます(この例では単純に進捗の値を1つ進めてその値を送信するnextメソッドが呼び出されています)。
なお、プル型の場合、サーバでの処理は進捗を送信した時点で終わるため、next等のメソッドが呼び出されたら、そのままPHPのexit関数が呼び出されます。そのため、(7)以降でさらに処理を行いたい場合には(6)でコメントアウトされているsetExitAfterFinishedメソッドを利用して設定を変更してください。また、Zend FrameworkのMVC環境を利用している場合には、renderメソッドが呼び出されるのを抑止するためにviewRendererアクションヘルパーなどを利用する必要があります。
(1)で設定したように、リクエストの結果をクライエント側で受け取るのはupdate関数です。
function update(http_obj) { //(8)JSON形式のデータの取り出し var data_text = http_obj.responseText; //(9)evalを使って変数dataに格納 eval('var data =' + data_text + ';'); // zend-progressbar-done を進捗状況に応じて伸ばす document.getElementById('zend-progressbar-done').style.width = data.percent + '%'; document.getElementById('status').value = data.percent + "% " + data.current + "/" + data.max + " " + data.timeTaken + "s elapsed (" + data.timeRemaining + "s remaining)" + data.finished; }
このupdate関数はリクエストオブジェクトを受け取り、(8)でその中にあるJSON形式のデータをテキストとして取り出します。そして(9)でJavaScriptのeval関数を利用して、データをdata変数に格納しています。
おわりに
今回は処理の進捗を表示するためのモジュール、Zend_ProgressBarを紹介しました。コンソールアプリから利用する場合はもちろん、今回紹介したパターンを利用すれば、Webアプリにプログレスバーを埋め込むことも簡単にできると思います。
次回はZend_Controllerモジュールまわりの処理が、最近どのように変わってきたかについての解説を行う予定です。