シムノート

PHPフレームワークSymfonyの学習帳

ユーザ用ツール

サイト用ツール


サイドバー

メニュー



このエントリーをはてなブックマークに追加

blog:2016-01-01:doctrine入門_entity_repositories

Doctrine入門 : (9) エンティティレポジトリ

EntityRepository

Doctrineではモデルからクエリーのロジックを切り離す為にRepositoryを使います。デフォルトで全てのエンティティはEntityRepositoryを使用します。Productエンティティをnameで検索したい場合は以下のようになります。

$product = $entityManager->getRepository('AppBundle:Product')
                         ->findOneBy(array('name' => $productName));

findOneBy()メソッドは検索条件となる項目と値の配列を引数に取ります。

もし条件に合う全てのエンティティを取得したい場合は、findBy()を使います。statusがCLOSEのBugを全て検索したい場合は以下のようになります。

$bugs = $entityManager->getRepository('AppBundle:Bug')
                      ->findBy(array('status' => 'CLOSE'));

foreach ($bugs as $bug) {
    // do stuff
}

Repositoryの作成

デフォルトのEntityRepositoryの機能を拡張して、エンティティ専用のレポジトリクラスを作成することが出来ます。そして、全ての特化したDQLをそのクラスの中に格納します。

BugRepositoryを以下のように作成します。

<?php

namespace AppBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;

class BugRepository extends EntityRepository
{
    public function getRecentBugsQuery()
    {
        $dql = "SELECT b, e, r FROM AppBundle:Bug b " .
               "JOIN b.engineer e JOIN b.reporter r " .
               "ORDER BY b.created DESC";

        return $this->getEntityManager()->createQuery($dql);
    }

    public function getRecentBugsArrayQuery()
    {
        $dql = "SELECT b, e, r, p FROM AppBundle:Bug b " .
               "JOIN b.engineer e JOIN b.reporter r JOIN b.products p " .
               "ORDER BY b.created DESC";

        return $this->getEntityManager()->createQuery($dql)
                    ->setHydrationMode(Query::HYDRATE_ARRAY);
    }

    public function getUsersBugsQuery($userId)
    {
        $dql = "SELECT b, e, r FROM AppBundle:Bug b " .
               "JOIN b.engineer e JOIN b.reporter r " .
               "WHERE b.status = 'OPEN' AND e.id = ?1 OR r.id = ?1 " .
               "ORDER BY b.created DESC";

        return $this->getEntityManager()->createQuery($dql)
                    ->setParameter(1, $userId);
    }

    public function getOpenBugsByProductQuery()
    {
        $dql = "SELECT p.id, p.name, count(b.id) AS openBugs FROM AppBundle:Bug b ".
               "JOIN b.products p WHERE b.status = 'OPEN' GROUP BY p.id";

        return $this->getEntityManager()->createQuery($dql)
                    ->setHydrationMode(Query::HYDRATE_SCALAR);
    }
}

このBugRepositoryを使用するには、BugエンティティのDoctrineメタ言語を調整する必要があります。

<?php
// ...

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\BugRepository")
 * @ORM\Table(name="bug")
 */
class Bug
{
    // ...
}

Controllerの修正

コントローラー内のクエリーロジックを削除して、代わりに先ほど作成したBugRepositoryを使うよう修正します。

// ...
class BugController extends Controller
{
    // ...
    public function indexAction(Request $request)
    {
        /** @var Query $query */
        $query = $this->getDoctrine()->getRepository('AppBundle:Bug')
            ->getRecentBugsArrayQuery();

        $paginator = $this->get('knp_paginator');
        /** @var SlidingPagination $pagination */
        $pagination = $paginator->paginate(
            $query,
            $request->query->getInt('page', 1), // page number
            5  // limit per page
        );

        return $this->render('bug/index.html.twig', array(
            'pagination' => $pagination,
        ));
    }
    // ...
}

// ...
class UserController extends Controller
{
    // ...   
    public function showAction(User $user)
    {
        $deleteForm = $this->createDeleteForm($user);

        $bugs = $this->getDoctrine()->getRepository('AppBundle:Bug')
            ->getUsersBugsQuery($user->getId())
            ->getResult();

        return $this->render('user/show.html.twig', array(
            'user' => $user,
            'delete_form' => $deleteForm->createView(),
            'bugs' => $bugs,
        ));
    }    
    // ...
}

// ...
class ProductController extends Controller
{
    // ...
    public function indexAction()
    {
        $products = $this->getDoctrine()->getRepository('AppBundle:Bug')
            ->getOpenBugsByProductQuery()
            ->getResult();

        return $this->render('product/index.html.twig', array(
            'products' => $products,
        ));
    }
    // ...
}

動作確認

Bug一覧画面、User表示画面、Product一覧画面を表示して動作確認をしてください。

まとめ

Doctrine入門は今回で最終回となります。いかがだったでしょうか?ぜひ、オリジナルのGetting Started with Doctrineも読んでみてください。


Comments



184 +8 = ?
blog/2016-01-01/doctrine入門_entity_repositories.txt · 最終更新: 2016/01/20 06:59 by tsubo