blogチュートリアル(7) 記事の追加 ================================ .. note:: この記事は、Symfony 2.0.7 で動作確認しています。 これまでのステップでデータベースに登録されている記事を表示できるようになりました。 次はいよいよ、フォームを作成してデータを追加・編集できるよにしてみましょう。 記事を追加するページのルーティングの作成 ---------------------------------------- 記事を追加するページが増えますので、対応するルーティングを追加する必要があります。 ``src/My/BlogBundle/Resources/config/routing.yml`` に ``blog_new`` ルート(route)を追加してください。 .. code-block:: yaml # src/My/BlogBundle/Resources/config/routing.yml blog_index: pattern: / defaults: { _controller: MyBlogBundle:Default:index } blog_new: pattern: /new defaults: { _controller: MyBlogBundle:Default:new } blog_show: pattern: /{id}/show defaults: { _controller: MyBlogBundle:Default:show } .. note:: ``{id}`` の条件として数値のみを受け付けるように制限することも可能です。この方法は\ `カスタマイズ編のルーティングのページ`_\ にて説明しています。 Postモデル用のフォームの作成 ---------------------------- 続いて、Default コントローラに記事追加用の ``new`` アクションを追加します。\ ``use`` 行を追加していることに注意してください。 .. code-block:: php // src/My/BlogBundle/Controller/DefaultController.php use My\BlogBundle\Entity\Post; // ... class DefaultController extends Controller { // ... public function newAction() { // フォームのビルド $form = $this->createFormBuilder(new Post()) // ここでPostクラスを使うため、ファイルの先頭あたりにuseを追加していることに注意 ->add('title') ->add('body') ->getForm(); // バリデーション $request = $this->getRequest(); if ('POST' === $request->getMethod()) { $form->bindRequest($request); if ($form->isValid()) { // エンティティを永続化 $post = $form->getData(); $post->setCreatedAt(new \DateTime()); $post->setUpdatedAt(new \DateTime()); $em = $this->getDoctrine()->getEntityManager(); $em->persist($post); $em->flush(); return $this->redirect($this->generateUrl('blog_index')); } } // 描画 return $this->render('MyBlogBundle:Default:new.html.twig', array( 'form' => $form->createView(), )); } } Symfony2では、\ ``FormBuilder`` を用いてコントローラのアクション内で簡単にフォームオブジェクトを作成することができます。 フォームオブジェクトを作成することで、バリデーションやDoctrineとの連携、フォームウィジェットのHTMLレンダリングなどを行うことができます。 このアクションでは、\ ``title`` と ``body`` の2つのフィールドを定義して、フォームを作成しています。 .. note:: このステップではフォームをコントローラ内で動的に生成しましたが、別のクラスに分離することもできます。 クラス化することで、アプリケーション内の別のアクションで再利用しやすくなります。 ``new`` アクションでは、\ ``GET`` メソッドでアクセスした場合と、\ ``POST`` メソッドでアクセスした場合の両方を扱っています。 最初にブラウザで「/blog/new」というURLにアクセスした場合は ``GET`` メソッドになりますが、 フォームに内容を入力して送信ボタンを押した場合は ``POST`` メソッドになります。 ``POST`` メソッドでアクションが実行された場合は、送信されたデータをフォームオブジェクトに\ **バインド**\ しています。 こうすることで、フォームオブジェクトに送信されたデータが統合されます。 .. note:: CakePHPのチュートリアルでは、フォームの初回表示と投稿時でのアクション内の分岐を ``$this->data`` の有無で判断しています。 symfony 1.x系やSymfony2では、REST(ful)の概念に基づき、このような判定をHTTPメソッドで行います。 フォームにデータをバインドすると、\ ``isValid()`` メソッドを実行してデータのバリデーション(検証)を実行できるようになります。 今のところ、バリデーションルールを追加していないので、あまり意味はありません。 バリデーションを通過した ``Post`` オブジェクトをフォームオブジェクトから取り出すには、\ ``getData()`` メソッドを使います。 フォームから取り出したオブジェクトをデータベースに登録するには、\ ``persist()`` メソッドで ``EntityManager`` に対して永続化指示を行った後、\ ``EntityManager`` の ``flush()`` メソッドを呼び出します。 .. note:: ``Post`` オブジェクトを ``persist()`` するときに、\ ``createdAt`` と ``updatedAt`` の値を手動で代入しています。 Doctrine2の ``Timestampable`` 拡張機能をインストールすると、この代入を自動で行うようにもできます。 この方法は\ `カスタマイズ編の投稿日時・更新日時の自動挿入のページ`_\ で説明しています。 最後の数行は \ ``GET`` メソッドでアクセスされたときと、\ ``POST`` メソッドだがバリデーションに失敗した時に実行されます。 今まで見てきたアクションと同様に、入力フォーム用のテンプレートをレンダリングしています。 ここでは、フォームオブジェクトを描画可能な ``FormView`` オブジェクトに変換するために ``createView()`` メソッドを呼び出し、その結果をテンプレートにパラメータとして引き渡しています。 フォームを表示するテンプレートの作成 ------------------------------------ 最後に、表示用のテンプレートを作成します。 .. code-block:: jinja {# src/My/BlogBundle/Resources/views/Default/new.html.twig #}