blogチュートリアル(9) 記事の追加

これまでのステップで、データベースに登録されているデータを表示できるようになりました!

次はいよいよ、フォームを作成してデータを追加・編集できるようにしてみましょう。

Postモデル用のフォームの編集

symfonyでモデルの生成コマンドを実行すると、モデルに対応するフォームクラス群も自動的に生成されています。 1つのモデルにつき、対応する1つのフォームクラスが生成されます。 フォームクラス群は、lib/form/doctrineディレクトリに生成されています。

sf_sandbox/
  lib/
    form/
      doctrine/
        PostForm.class.php
        base/
          BasePostForm.class.php

これらのフォームクラスを使うことで、特定のモデルに対するCRUDを簡単に作成できるだけでなく、フォームのカスタマイズも行えるようになっています。

モデルクラスと同じように、フォームクラスにも~Form.class.phpBase~Form.class.phpの2つのクラスがあります。 Base~クラスは基本設定が記述してあるクラスで、編集してはいけないことに注意して下さい。 フォームクラスをカスタマイズする場合は、Baseのついていないファイルを編集します。

では、lib/form/doctrine/PostForm.class.phpをエディタで開き、以下のように編集してください。

class PostForm extends BasePostForm
{
  public function configure()
  {
    $this->useFields(array('id', 'title', 'body'));
  }
}
 

生成されたフォームクラスには、デフォルトでデータベースのすべてのフィールドに対応するウィジェットが含まれています。 しかし、今回使用するのはidtitlebodyフィールドのみなので、useFieldsメソッドでこのフィールド以外を使わないよう設定しています。

PostFormクラスにほとんどコードが書かれていないにもかかわらずウィジェットなどが表示されるのは、 継承元のBasePostFormクラスにウィジェットの定義が自動生成されているためです。

PostFormを使うnewアクションを作成

次は、作成したPostFormを使って入力画面を処理するnewアクションを作成します。 apps/frontend/modules/post/actions/actions.class.phpファイルをエディタで開き、以下のコードをクラス内の末尾に追加してください。

public function executeNew(sfWebRequest $request)
{
  $this->form = new PostForm();
  if ($request->isMethod(sfRequest::POST))
  {
    $this->form->bind($request->getParameter($this->form->getName()));
    if ($this->form->isValid())
    {
      $this->form->save();
      $this->getUser()->setFlash('info', 'データを保存しました。');
      $this->redirect('post/index');
    }
  }
}
 

このアクションでは、GETメソッドでアクセスした場合とPOSTメソッドでアクセスした場合の両方を扱っています。 最初にブラウザで「post/new」というURLにアクセスした場合はGETメソッド、 フォームに内容を入力して送信ボタンを押した場合はPOSTメソッドになります。 POSTメソッドの場合は、送信されたデータをフォームにバインドし、フォームに関連付けられているオブジェクト=Postモデルのレコードを保存しています。

CakePHPのチュートリアルでは、フォームの初回表示と投稿時でのアクション内の分岐を、データの有無で判断しています。 symfonyではREST(ful)の概念に基づき、このような判定をHTTPメソッドで行います。 具体的には、newアクションでの初回表示時はGETメソッドによるアクセス、フォームを送信した場合はPOSTメソッドによるアクセスとなっていることを利用します。

データの保存後は、flashメッセージを設定してpost/index(一覧画面)へリダイレクトしています。 symfonyのflash機能では、単にメッセージを記録するのみです。(次のリダイレクト先まで有効) リダイレクト後のビューにて、flashの文字列を取得して表示するようにしています。

actions.class.php内にrequireincludeを記述しなくてもPostFormクラスを利用できるのは、 symfonyによってPostFormクラスがオートロード対象に設定されるためです。 symfonyのオートロード機能については、symfonyのオートロードで説明しています。

フォームを表示するビューの作成

最後に、表示用のビューを作成します。 apps/frontend/modules/post/templates/newSuccess.phpファイルを作成し、以下のコードを入力して保存してください。

<?php echo $form->renderFormTag(url_for('post/new')) ?>
<table>
<?php echo $form ?>
</table>
<input type="submit" name="add" value="add" />
</form>
 

まず、コードの先頭行ではフォームオブジェクトのrenderFormTagメソッドを使ってformタグ(開始タグ)を生成しています。1番目の引数でフォームの送信先のアクションを指定しています(内部URI形式)。 renderFormTagメソッドを使うと、新規データの追加フォームの場合はPOSTメソッドになります。

3行目では、$formをechoしています。$form変数にはPostFormのインスタンスが格納されています。 この変数をechoすると、フォームのウィジェットが描画されます。ウィジェットを描画する際に、デフォルトではテーブルタグの行として描画されますので、この出力部分をtableの開始タグと終了タグで囲んでいます。

symfonyには、フォームの終了タグをレンダリングするヘルパーはありません。 ですので、フォームの終了タグは直接記述する必要があります。

動作の確認

コードの追加が完了したら、ブラウザで「http://localhost/sf_sandbox/web/frontend_dev.php/post/new」にアクセスしてみてください。新規追加用のフォームが表示されたら、何かデータを入力して「add」ボタンをクリックし、データが正しく追加されるかどうか確認してください。