namespaceやvalidationを設定しつつフォームを利用してみた
PhalconのフォームはCakePHPのフォームとは異なる
Phalconにもフォームを効率的に組むための仕組みがある。
しかし、CakePHPのform helperと比べると利用の仕方が異なっている。Phalconのフォームでは、フォーム専用のclassを定義して、そのクラスをコントローラから呼び出すという方法を採るのが一般的なようだ。フォームクラスの具体例をあげてみたい。
app\forms\PostsForm.php
として下のフォームを作成する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 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に渡す
フォームを定義したのでコントローラからそのフォームを呼び出してみたい。呼び出し部分が以下のコード
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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は以下のように組むことができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | < 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チェックを行うコードが下のコードになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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側で展開されることになる。
参考として上のサンプルコードで作成したモデルも載せておこうと思う。
1 2 3 4 5 6 7 8 9 10 | namespace Blog\Models; use Phalcon\Mvc\Model; class Posts extends Model { public function initialize(){ $this ->setSource( 'posts' ); } } |
フォームクラスにvalidationを定義しているので、モデル側はシンプルになっている。
CakePHPのform helperとはやり方が異なるが、Phalconでも効率的にフォームを組むことができる。