| 入力キー | 表示名 | 制限 |
|---|---|---|
| name | 名前 | 必須/全角12文字以内 |
| メールアドレス | 必須/255バイト以内/メールアドレス形式 | |
| age | 年齢 | 自然数/18~60 |
| sex | 性別 | 必須/1,2のいずれか |
まず、app/forms に Forms_Userクラス を作成します。Form_Object は全てのフォームクラスの基底クラスです。
app/forms/User.php
class Forms_User extends Form_Object
{
}
次にすることは、入力名に対応する表示名を設定することです。
class Forms_User extends Form_Object
{
protected $displayNames = array(
"name" => "名前",
"email" => "メールアドレス",
"age" => "年齢",
"sex" => "性別",
);
}
次は、バリデータに標準で実装されているバリデーションメソッドを各入力に充てていきます。バリデーションメソッドなどの詳細はバリデーションの章を参照してください。
class Forms_User extends Form_Object
{
...
protected $validators = array(
"name" => array("required", "strwidth(24)"),
"email" => array("required", "strlen(255)"),
"age" => array("nnumber", "min(18)", "max(60)"),
"sex" => array("required"),
);
}
とりあえずこの状態で、フォームを動作させてみましょう。フォーム表示アクションでは、先ほど作成したフォームオブジェクトをビューに渡します。
app/index/controllers/Index.php
class Index_Controllers_Index extends Sabel_Controller_Page
{
public function index()
{
$this->userForm = new Forms_User();
}
}
ビュー(テンプレート)でフォームを作成します。フォームオブジェクトの n()メソッド は getDisplayName() のエイリアスです。
<?php if ($userForm->hasError()) : ?>
<?php echo $this->partial("error", array("errors" => $userForm->getErrors())) ?>
<?php endif ?>
<form action="<?php echo uri('a: post') ?>" method="post">
<dl>
<dt><?php echo $userForm->n("name") ?></dt>
<dd><?php echo $userForm->text("name") ?></dd>
<dt><?php echo $userForm->n("email") ?></dt>
<dd><?php echo $userForm->text("email") ?></dd>
<dt><?php echo $userForm->n("age") ?></dt>
<dd><?php echo $userForm->text("age") ?></dd>
<dt><?php echo $userForm->n("sex") ?></dt>
<dd><?php echo $userForm->select("sex", array("" => "", 1 => "女性", 2 => "男性")) ?></dd>
<dd>
<input type="submit" value="Post" />
</dd>
</dl>
</form>
フォームが作成できたので、次はPOST先のアクションを実装します。Formオブジェクト の submit()メソッド の第1引数は入力値の配列なので、リクエストオブジェクトからPOSTされた値を配列で受け取り、それをそのまま渡します。第2引数は入力として有効な入力名を渡しています。次章で扱うModelフォームの場合に特に重要で、この仕組みが無いと攻撃者がHTMLを書き換えた場合などに意図しないデータが入力されてしまうためです。
class Index_Controllers_Index extends Sabel_Controller_Page
{
...
public function post()
{
$form = new Forms_User();
$form->submit($this->request->fetchPostValues(), array(
"name", "email", "age", "sex"
));
if ($form->validate()) {
} else {
$this->userForm = $form;
$this->view->setName("index");
}
}
}
これでとりあえず、フォームが動作するようになりました。* 名前は必須です * メールアドレスは必須です * 性別は必須ですまた、名前に「あいうえおあいうえおあいうえお」を入力すると...
* 名前は全角12文字以内で入力してください年齢に「test」を入力すると...
* 年齢は整数で入力してください年齢に「3306」を入力すると...
* 年齢は60以下で入力してくださいなど、バリデーションが正しく行われていることが分かります。
class Forms_User extends Form_Object
{
...
public function validateEmail($name, $value)
{
if (!is_empty($value)) {
if (形式が不正なら) {
return $this->getDisplayName($name) . "の形式が不正です";
}
}
}
public function validateSex($name, $value)
{
if (!is_empty($value) && !in_array((int)$value, array(1, 2), true)) {
return $this->getDisplayName($name) . "の値が不正です";
}
}
}
※メールアドレス形式のバリデーションは要求や実装者の思想などによって大きく変わるため、実装は省略しています。あなたのいつものチェックコードをコピーしてください。
class Forms_User extends Form_Object
{
...
protected $validators = array(
"name" => ...,
"email" => array("required", "strlen(255)", "validateEmail"),
"age" => ...,
"sex" => array("required", "validateSex"),
);
}
なお、今回は性別をセレクトボックスで入力させているため、このようなカスタムバリデーションはやりすぎかもしれません。何らかの方法で1, 2以外の値をPOSTしたとしても、不都合なこと(検索にひっかからないなど)がそのユーザ自身に対してのみしか発生しないのならば無視できるためです。
<input id="myid" class="myclass" type="text" name="test" value="" />なお、radioとcheckboxに関しては $attrs に "id=" を含めても出力されるHTMLには反映されません。選択要素それぞれにlabelで使用するidを、内部で自動的に付加するためです。
<input id="radio_1" class="myclass" type="radio" name="test" value="1" /><label for="radio_1">one</label> <input id="radio_2" class="myclass" type="radio" name="test" value="2" /><label for="radio_2">two</label>select()メソッド の第2引数 $values は通常配列ですが、下記のように特殊な文字列を渡すことも可能です。
$form->select("test", "20:100")
上記では、20から100の数値を選択するセレクトボックスが作成されます。<select name="test"> <option value="20">20</option> <option value="21">21</option> <option value="22">22</option> ... <option value="100">100</option> </select>dateやdatetimeの$includeBlankをtrueにすると、各セレクトボックスの先頭に空optionが追加されます。