前回は、blogチュートリアルを 10 章まで進め、Fixtureを導入してテストコードを書く準備を整えました。
-
[Symfony2] DoctrineFixturesBundleをPHPUnitと連動させる方法
前回の記事で、Symfony2のblogチュートリアルにファンクショナルテストを書きました。 このテストにはテストメソッ ...
続きを見る
今回は、チュートリアルを 11 章まで写経した後に、私が独自にリファクタリングをした内容を紹介します。
リファクタリングでは下記の内容を試してみました。
- GETリクエストとPOSTリクエストのアクションを分離
- Repositoryクラスの導入
- Repositoryクラスのテストコードを記述
- Formクラスのテストコードを記述
動作確認環境
- Symfony 2.0.11
- PHP 5.3.10
- PHPUnit 3.6.10
目次
11 章まで進める
まずは blogチュートリアル(11) まとめと応用 まで終わらせます。
GETリクエストとPOSTリクエストのアクションを分離
オリジナルのコードでは、コントローラ内でGETかPOSTかを判断して処理を分岐させていました。コントローラを短くするために、アクションを分けました。
newActionのみ抜粋して紹介します。
routing
src/My/BlogBundle/Resources/config/routing.yml
blog_new:
pattern: /new
defaults: { _controller: MyBlogBundle:Default:new }
blog_new_post:
pattern: /new
defaults: { _controller: MyBlogBundle:Default:newPost }
requirements:
_method: POST
Controller
src/My/BlogBundle/Controller/DefaultController.php
public function newAction()
{
$form = $this->createForm(new PostType(), new Post());
return $this->render('MyBlogBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
public function newPostAction()
{
$form = $this->createForm(new PostType(), new Post());
$form->bindRequest($this->getRequest());
if (!$form->isValid()) {
return $this->render('MyBlogBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
//...
}
Repositoryクラス
データベース関連のロジックをコントローラから分離してコントローラを短くするため、また、テストコードを書きやすくするためにRepositoryクラスを導入しました。
blogチュートリアルは複雑なデータベース関連の処理を行なっていませんので、コントローラはそれほど短くなりませんでした。
将来、関連するエンティティが増えてくるとRepositoryクラス導入のメリットが見えてくると思います。
DB更新系メソッドの戻り値は悩みましたが、テストを書きやすくするためにBooleanとしました。
Repositoryクラス
src/My/BlogBundle/Repository/PostRepository.php
<?php
namespace My\BlogBundle\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
use My\BlogBundle\Entity\Post;
/**
* PostRepository
*/
class PostRepository extends EntityRepository
{
/**
* search
*
* @return array Array of PostEntity
*/
public function search()
{
$em = $this->getEntityManager();
return $em->getRepository('MyBlogBundle:Post')->findAll();
}
/**
* searchOneById
*
* @param Integer $id
* @return \My\BlogBundle\Entity\Post
* @throws \Doctrine\ORM\NoResultException
*/
public function searchOneById($id)
{
$em = $this->getEntityManager();
$post = $em->getRepository('MyBlogBundle:Post')->findOneById($id);
if (empty($post)) {
throw new NoResultException;
}
return $post;
}
/**
* insert
*
* @param \My\BlogBundle\Entity\Post $post
* @return Boolean
*/
public function insert(Post $post)
{
$em = $this->getEntityManager('MyBlogBundle:Post');
$em->persist($post);
$em->flush();
return true;
}
/**
* delete
*
* @param Integer $id
* @return Boolean
* @throws \Doctrine\ORM\NoResultException
*/
public function delete($id)
{
$em = $this->getEntityManager();
$post = $this->searchOneById($id);
$em->remove($post);
$em->flush();
return true;
}
/**
* update
*
* @param \My\BlogBundle\Entity\Post $post
* @param Integer $id
* @return Boolean
* @throws \Doctrine\ORM\NoResultException
*/
public function update(Post $post)
{
$em = $this->getEntityManager();
$this->searchOneById($post->getId());
$em->flush();
return true;
}
}
コントローラ
Repositoryクラスの導入で、若干短くなりました。
<?php
namespace My\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\BlogBundle\Form\PostType;
use My\BlogBundle\Entity\Post;
use Doctrine\ORM\NoResultException;
class DefaultController extends Controller
{
public function indexAction()
{
$em = $this->getDoctrine()->getEntityManager();
$posts = $em->getRepository('MyBlogBundle:Post')->search();
return $this->render('MyBlogBundle:Default:index.html.twig', array('posts' => $posts));
}
public function newAction()
{
$form = $this->createForm(new PostType(), new Post());
return $this->render('MyBlogBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
public function newPostAction()
{
$form = $this->createForm(new PostType(), new Post());
$form->bindRequest($this->getRequest());
if(!$form->isValid()) {
return $this->render('MyBlogBundle:Default:new.html.twig', array(
'form' => $form->createView()
));
}
$em = $this->getDoctrine()->getEntityManager();
$em->getRepository('MyBlogBundle:Post')->insert($form->getData());
$this->get('session')->setFlash('my_blog', '記事を追加しました');
return $this->redirect($this->generateUrl('blog_index'));
}
public function showAction($id)
{
try {
$em = $this->getDoctrine()->getEntityManager();
$post = $em->getRepository('MyBlogBundle:Post')->searchOneById($id);
return $this->render('MyBlogBundle:Default:show.html.twig', array('post' => $post));
} catch (NoResultException $e) {
throw new NotFoundHttpException('The post does not exist.');
}
}
public function deleteAction($id)
{
try {
$em = $this->getDoctrine()->getEntityManager();
$em->getRepository('MyBlogBundle:Post')->delete($id);
$this->get('session')->setFlash('my_blog', '記事を削除しました');
return $this->redirect($this->generateUrl('blog_index'));
} catch (NoResultException $e) {
throw new NotFoundHttpException('The post does not exist.');
}
}
public function editAction($id)
{
try {
$em = $this->getDoctrine()->getEntityManager();
$post = $em->getRepository('MyBlogBundle:Post')->searchOneById($id);
$form = $this->createForm(new PostType(), $post);
return $this->render('MyBlogBundle:Default:edit.html.twig', array(
'post' => $post,
'form' => $form->createView(),
));
} catch (NoResultException $e) {
throw new NotFoundHttpException('The post does not exist.');
}
}
public function editPostAction($id)
{
try {
$em = $this->getDoctrine()->getEntityManager();
$post = $em->getRepository('MyBlogBundle:Post')->searchOneById($id);
$form = $this->createForm(new PostType(), $post);
$form->bindRequest($this->getRequest());
if (!$form->isValid()) {
return $this->render('MyBlogBundle:Default:edit.html.twig', array(
'post' => $post,
'form' => $form->createView(),
));
}
$post = $em->getRepository('MyBlogBundle:Post')->update($form->getData());
$this->get('session')->setFlash('my_blog', '記事を編集しました');
return $this->redirect($this->generateUrl('blog_index'));
} catch (NoResultException $e) {
throw new NotFoundHttpException('The post does not exist.');
}
}
}
次回は form と repository にテストコードを追加してみます
-
Symfony2のblogチュートリアルをリファクタリングしてみた(repositoryとformのテスト)
前回の記事の続きです。 引き続き、repository と form のテストを書いてみたので紹介します。 動作確認環境 ...
続きを見る