namespaceやvalidationを設定しつつフォームを利用してみた
PhalconのフォームはCakePHPのフォームとは異なる
Phalconにもフォームを効率的に組むための仕組みがある。
しかし、CakePHPのform helperと比べると利用の仕方が異なっている。Phalconのフォームでは、フォーム専用のclassを定義して、そのクラスをコントローラから呼び出すという方法を採るのが一般的なようだ。フォームクラスの具体例をあげてみたい。
app\forms\PostsForm.php
として下のフォームを作成する。
namespace Blog\Forms; use Phalcon\Forms\Form; use Phalcon\Forms\Element\Text; use Phalcon\Forms\Element\Textarea; use Phalcon\Forms\Element\Submit; use Phalcon\Validation\Validator\PresenceOf; class PostsForm extends Form { public function initialize($entity = null, $options = null) { // title $title = new Text('title'); $title->setLabel('Title'); $title->addValidators(array( new PresenceOf(array( 'message' => 'The title is required' )) )); $this->add($title); // body $body = new Textarea('body'); $body->setLabel('Body'); $body->addValidators(array( new PresenceOf(array( 'message' => 'The body is required' )) )); $this->add($body); // Post $this->add(new Submit('Post', array( 'class' => 'btn btn-success' ))); } public function messages($title) { if ($this->hasMessagesFor($title)) { foreach ($this->getMessagesFor($title) as $message) { $this->flash->error($message); } } } }
上のコードでは、
- title
- body
というテキストボックスとテキストエリアを入力するためのフォームを構成している。CakePHPと異なり、冒頭で必要なフォーム部品や設定するvalidationだけをuseすることが可能。上の例では、
PresenceOf
という入力必須項目を設定するためのvalidation機能だけをuseしてある。
このフォームをコントローラから呼び出して利用するので、Phalconにおけるフォームのvalidationはモデル側には設定せずにフォームクラスに定義することになっている。フォームを持たないREST APIでは、モデル側にvalidationを定義することも可能。
Controllerでformを生成しViewに渡す
フォームを定義したのでコントローラからそのフォームを呼び出してみたい。呼び出し部分が以下のコード
namespace Blog\Controllers; use Blog\Forms\PostsForm; use Blog\Models\Posts; class PostController extends ControllerBase { public function addAction() { $form = new PostsForm(); $this->view->form = $form; } }
2行に分けて書いてみたが$formを無くして1行で書いても問題はない。2行に分けたのは、その間にPOSTリクエスト(フォームがsubmitされた)の処理を挟むことになるため分けて書いてみた。POSTリクエストの処理を追加する前に、上のコードでView側にフォームの情報が渡されていることを確認したい。Voltテンプレートを利用した場合はViewは以下のように組むことができる。
<div> {{ form() }} <div> <h2>New Post</h2> </div> <table> <tr> <td>{{ form.label('title') }}</td> <td> {{ form.render('title') }} {{ form.messages('title') }} </td> </tr> <tr> <td>{{ form.label('body') }}</td> <td> {{ form.render('body') }} {{ form.messages('body') }} </td> </tr> <tr> <td></td> <td>{{ form.render('Post') }}</td> </tr> </table> <hr> </form> </div>
Phalconのフォーム生成プロセスは、
- フォームクラスでひな形を定義
- コントローラでフォームを生成
- Viewで展開
という過程を経て行われる。
Controllerでvalidationチェックを行う
ここまでのコードで定義したフォームをViewに展開することができた。しかし、submitボタンを押してもPOSTリクエストが処理されない状態になっている。コントローラでPOSTリクエストを判定しvalidationチェックを行うコードが下のコードになる。
public function addAction() { $form = new PostsForm(); // POSTリクエストの判定 if ($this->request->isPost()) { // validationチェック if ($form->isValid($this->request->getPost()) != false) { // 新規モデルの生成 $post = new Posts(); // データの生成 $post->assign(array( 'title' => $this->request->getPost('title'), 'body' => $this->request->getPost('body'), )); // dbへ保存 if ($post->save()) { return $this->dispatcher->forward(array( 'controller' => 'post', 'action' => 'index' )); } $this->flash->error($post->getMessages()); } } $this->view->form = $form; }
validationでエラーとなった場合には、
$form
に対してエラー情報が追加され、エラー情報付きのフォームがView側で展開されることになる。
参考として上のサンプルコードで作成したモデルも載せておこうと思う。
namespace Blog\Models; use Phalcon\Mvc\Model; class Posts extends Model { public function initialize(){ $this->setSource('posts'); } }
フォームクラスにvalidationを定義しているので、モデル側はシンプルになっている。
CakePHPのform helperとはやり方が異なるが、Phalconでも効率的にフォームを組むことができる。