導入

導入 – このパッケージを使用すると、何がうれしいのか

なぜ "Controller" なの?

このパッケージは、PageController デザインパターンを実装したものです。 これは、リクエストの受け取りと (受け取った GET データあるいは POST データに依存した) アクションの実行をひとつのページで行うことを意味します。 PageController パターンについては、 Martin Fowler のウェブサイト および WACT プロジェクトのウェブサイト でより詳しく説明されています。

QuickForm においてこれがどのような意味を持つかというと、 ひとつのスクリプト内で、リクエストの内容に応じて さまざまなフォームの表示や入力内容の検証を行うということです。 これにより、複数ページで構成される複雑なフォーム (ウィザードなどを思い浮かべでください) を ほんとうに簡単に作成できるようになります。

PageController パターンの最も基本的な実装は、以下のようになります。

<?php
switch ($_REQUEST['action']) {
    case 
'foo'
        
doFoo(); 
        break;
    case 
'bar'
        
doBar(); 
        break;
    default:
        echo 
'Hello, world!';
}
?>

HTML_QuickForm_Controller はこれより少しだけ複雑で、 3 つの基底クラスが存在します。

  • HTML_QuickForm_Controller: このクラスは、リクエストからアクション名を抽出して 適切なハンドラをコールします。ここには複数のページが含まれます。
  • HTML_QuickForm_Page: このクラス (HTML_QuickForm を継承しています) は、 フォームの各ページを表します。
  • HTML_QuickForm_Action: このクラスは、Command デザインパターン (つまり、オブジェクト指向のコールバック) を実装します。

リクエストで送信されるアクションは ページ名とアクション名で構成され、それによって どのページ (例: 画面表示・フォームの検証など) がリクエストを処理するか・ そのページが何を行うのか が決まります。

基本的な使用例

セッションの初期化

ページ間でのデータのやりとりの必要がないため、この例ではセッションを使用しません。 しかし、実際に複数ページのフォームを使用する際にはきっとセッションが必要となるでしょう。 HTML_QuickForm_Controller は、セッションを自動的には開始 しません。コントローラクラスのインスタンスを作成する前に、 session_start() を明示的にコールする必要があります。

このパッケージの機能について理解するため、 HTML_QuickForm チュートリアル の例を HTML_QuickForm_Controller で書き直してみましょう。

基本的なコントローラの使用法

<?php
// コントローラを読み込みます
require_once 'HTML/QuickForm/Controller.php';
// 基底アクションクラスを読み込みます
// (これを継承したクラスをあとで作成します)
require_once 'HTML/QuickForm/Action.php';

// フォームを表すクラス
class FirstPage extends HTML_QuickForm_Page
{
    function 
buildForm()
    {
        
$this->_formBuilt true;

        
// フォームに要素を追加します
        
$this->addElement('header'null'QuickForm tutorial example');
        
$this->addElement('text''name''Enter your name:', array('size' => 50'maxlength' => 255));
        
// submit ボタンの名前を設定する方法に注意してください
        
$this->addElement('submit'$this->getButtonName('submit'), 'Send');

        
// フィルタと検証ルールを追加します
        
$this->applyFilter('name''trim');
        
$this->addRule('name''Please enter your name''required'null'client');

        
$this->setDefaultAction('submit');
    }
}

// フォームを処理するアクション
class ActionProcess extends HTML_QuickForm_Action
{
    function 
perform(&$page$actionName)
    {
        echo 
'<h1>Hello, ' htmlspecialchars($page->exportValue('name')) . '!</h1>';
    }
}

$page =& new FirstPage('firstForm');

// 'process' ハンドラのみを追加します
// コントローラはこれをデフォルトとして使用します
$page->addAction('process', new ActionProcess());

// コントローラをインスタンス化します
$controller =& new HTML_QuickForm_Controller('tutorial');

// フォーム要素のデフォルト値を設定します
$controller->setDefaults(array(
    
'name' => 'Joe User'
));

// コントローラにページを追加します
$controller->addPage($page);

// リクエストを処理します
$controller->run();
?>

もとのコードより冗長になってしまっていると思われるかもしれません。 確かにそのとおりですが、3 ページからなるウィザード形式のフォームを 作成する場合のことを考えてみましょう。HTML_QuickForm_Controller を使用している場合は、 HTML_QuickForm_Page のサブクラスを 3 つ作成し、 HTML_QuickForm_Action に基づいた 'process' イベントのハンドラを作成して それらをコントローラに追加するだけですみます。 しかし、HTML_QuickForm_Controller を使用していない場合は 大量のプログラミングが必要となることでしょう。

独自のページを作成する

まず HTML_QuickForm_Page のサブクラスを作成し、 buildForm() メソッドをオーバーライドする必要があります。 (QuickForm になじみが深い方なら) その内容は見慣れているでしょうが、多少の例外があります。

<?php
$this
->_formBuilt true;
?>

フォームの作成は "重たい" 処理です。そのため、 本当に必要な場合にのみ buildForm() をコールするようにします。この処理を 2 回コールする (そして要素のセットを 2 回取得する) ことを避けるためには $_formBuilt プロパティを設定します。

2 番目に注意すべき点は、以下の行です。

<?php
$this
->addElement('submit'$this->getButtonName('submit'), 'Send');
?>

getButtonName() メソッドを使用して送信ボタンの名前を指定し、 ボタンがクリックされた際に 'submit' アクションが実行されるようにしています。

3 番目は、以下の行です。

<?php
$this
->setDefaultAction('submit');
?>

フォームのボタンをクリックする以外にも、Enter キーを押すことで フォームを送信することができます。このような場合 ほとんどのブラウザでは特定の送信ボタンが押されたとは考えず、 そのためボタンの名前が送信されません。 setDefaultAction() で、このような場合にコールされるアクションを (フォームに特別な hidden フィールドを追加することで) 設定します。

独自のアクションを作成する

通常は、'process' および 'display' の 2 つのアクションについてのハンドラを作成する必要があります。 前者については、ここで説明することは困難です。というのも、 そのフォームで何をどのように処理すべきなのかを知っているのは あなた自身だけだからです。後者については、 HTML_QuickForm_Action_Display のサブクラスを作成してその _renderForm() メソッドをオーバーライドし、適切な レンダラ をコールして独自の出力を行えるようにする必要があります。

すべてをひとつにまとめる

次に、上で定義したページクラスのインスタンスを作成します。

<?php
$page 
=& new FirstPage('firstForm');
?>

そして、そこに独自のアクションハンドラを追加します。

<?php
$page
->addAction('process', new ActionProcess());
?>

フォームの入力内容が有効だった場合は、 'submit' アクションのデフォルトハンドラとして 'process' アクションがコールされます。

それから、コントローラのインスタンスを作成します。

<?php
$controller 
=& new HTML_QuickForm_Controller('tutorial');
?>

コントローラ名が必須パラメータであることに注意しましょう。 もしアプリケーション内で複数のコントローラを使用するのであれば、 それぞれ別の名前を指定する必要があります。なぜなら、 セッション内に値を保存する際にコントローラ名が使用されるからです。

それから、フォームのデフォルト値を設定してそれをページに追加します。

<?php
$controller
->setDefaults(array(
    
'name' => 'Joe User'
));
$controller->addPage($page);
?>

この方法以外にも、buildForm() の中でページの setDefaults() をコールする方法もあります。しかし、前者のアプローチが すべてのフォームのデフォルト値を一度に指定できるのに対して、 後者の方法では特定のページについてしか設定できません。

最後に、コントローラの run() メソッドをコールします。

<?php
$controller
->run();
?>

これにより、現在のアクション名を取得して適切なハンドラがコールされます。 以上です。

高度な使用例

は、パッケージのアーカイブに含まれています。 上で説明した例と似たものに加えて、 さらに 2 つの複数ページフォームの例が含まれています。

  • ウィザード: フォームの各ページには 'Next' ボタンおよび 'Back' ボタンが含まれており、 現在のページの入力内容が有効でない限り次のページには進めません。
  • タブ形式のフォーム: フォームはいくつかのページで構成されており、 対応するページに直接ボタンで移動できます。 共通 'Submit' ボタンが押されたときにのみ 入力内容が検証されます。
HTML_QuickForm_Controller (Previous) このパッケージの機能について理解する (Next)
Last updated: Sat, 23 Aug 2014 — Download Documentation
Do you think that something on this page is wrong? Please file a bug report or add a note.
View this page in:

User Notes:

Note by: Ed Greenberg
Look in the doc directory under pear...

pear/doc/HTML_QuickForm_Controller/examples/wizard.php

and others
Note by: powtac@gmx.de
Couldn't there be a example with 2 or more quickform pages?