前回でフォームを作り、データ送信まで完了しました。 今回はその 受信したデータ をDBに登録する部分をやってみようと思います。

受信したpost_idをPostエンティティに変換

存在しない投稿にコメントできてはいけないので、DBへ検索を行います。

SymfonyでDBを操作する際には、下記の3つのオブジェクトを使います。

  • Entity
  • テーブルのレコードにあたります。

  • EntityManager
  • レコードを操作するときは必ずこのオブジェクト越しに行います。

  • Repository
  • EntityManagerを保持したオブジェクトで、汎用的なレコード操作や等はここに書きます。

早速書いてみる

/**
 * @Route("/create/{post_id}", name="comment_create")
 * @Template()
 */
public function createAction($post_id)
{
    $entityManager = $this->getDoctrine()->getManager();
    $post = $entityManager->getRepository('QuartetBlogBundle:Post')->find($post_id);

    return new Response($post->getTitle());
}

これで記事タイトルが表示されるようになります。

f79ccd53-cab1-5f21-7efa-d1c63b0daaa8-1024x572

@ParamConverterを使う方法

@ParamConverter Symfonyではパラメータとエンティティの変換を定義しておくと、コントローラーの引数に渡ってくる時点でエンティティとして受け取る事ができます。

これを使うとコントローラーがよりスッキリします。

まずは使うクラスをインポートします。

<?php
// CommentController.php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Quartet\Bundle\BlogBundle\Entity\Post;

アノテーションで関連を定義

/**
 * @Route("/comment")
 */
class CommentController extends Controller
{
    /**
     * @Route("/create/{post_id}", name="comment_create")
     * @Template()
     * @ParamConverter("post", class="QuartetBlogBundle:Post", options={"id" = "post_id"})
     */
    public function createAction(Post $post)
    {
        return new Response($post->getTitle());
    }
}

QuartetBlogBundle:Post エンティティの id = post_id に相当するレコードを $post にするという意味

あとは受信したフォームのデータと関連づけて、Commentテーブルに登録すれば完了です。

受信したデータをエンティティに変換する

まずは使うクラスをインポートします。

<?php
// CommentController.php
use Symfony\Component\HttpFoundation\Request;

Requestオブジェクトを引数で取得します。

/**
 * @Route("/comment")
 */
class CommentController extends Controller
{
    /**
     * @Route("/create/{post_id}", name="comment_create")
     * @Template()
     * @ParamConverter("post", class="QuartetBlogBundle:Post", options={"id" = "post_id"})
     */
    public function createAction(Request $request, Post $post)
    {
        $comment = new Comment();
        $form = $this->createForm(new CommentType(), $comment);

        $form->handleRequest($request);

        return new Response($post->getTitle() . ' ' . $comment->getContent());
    }
}

途中まではフォーム作成と一緒です。

  1. エンティティを作成
  2. エンティティとフォームを関連づける
  3. フォームとリクエストを関連づける
  4. 作成したエンティティにデータが設定された状態になる。
  5. 完成!

コメントを入力して送信すると…

screenshot

タイトルとコメント両方が表示されます。

screenshot

変換したエンティティをDBに登録

Comment エンティティが完成したので、Postエンティティを設定して登録します。

/**
 * @Route("/comment")
 */
class CommentController extends Controller
{
    /**
     * @Route("/create/{post_id}", name="comment_create")
     * @Template()
     * @ParamConverter("post", class="QuartetBlogBundle:Post", options={"id" = "post_id"})
     */
    public function createAction(Request $request, Post $post)
    {
        $comment = new Comment();
        $comment->setPost($post);

        $form = $this->createForm(new CommentType(), $comment);

        $form->handleRequest($request);

        if ($form->isValid()) {

            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($comment);
            $entityManager->flush();

            $this->redirect($this->generateUrl('post_show', ['id' => $post->getId()]));
        }

        return new Response($post->getTitle() . ' ' . $comment->getContent());
    }
}

追記した処理は

  1. エンティティ同士の設定(インスタンスを設定するだけ)
  2. エンティティマネージャーに登録を依頼する。(登録はここまで)
  3. 記事表示画面にリダイレクト

これだけです。

最後のレスポンスをreturnしている部分はフォームのバリデーションに失敗している部分なので、フォームの再表示等を行います。 CRUDを生成したPostController::createActionが参考になるので真似すればOKです。

まとめ

色々なオブジェクトが登場しましたが、CakePHPとは違いコントローラーの中ではフォームのキーや、テーブルの物理名が全く出てきません。

これを関心の分離といい、オブジェクト指向言語の基本の1つになります。

  • クラスの担当すべき部分だけにフォーカスできる。
  • テストデータの準備が容易