Symfony에서 Repository와 Entity의 임피던스 미스 매치를 제거합니다.

개요



동기



지난번 에 이어, 임피던스 미스 매치를 해소하는 시리즈의 제2탄입니다.

Symfony (Doctrine)에서 집계 함수의 결과를 다룰 때 기존 엔티티와 일치하지 않는 경우가 있습니다.

환경



PHP 5.6.9
심포니 3.1.2

사용 사례



날짜별로 주문 수와 총 금액을 집계하여 목록으로 표시합니다.

모델



상품 (ID, 명칭, 가격)
주문 (ID, 금액)
주문 항목 (ID, 주문 ID, 상품 ID, 수량, 금액)

상세



화면 이미지





해결책


  • 집계 결과와 일치하는 엔티티를 만들어 봅시다!


  • 사용 전 모델





    사용 후 모델





    샘플 코드



    컨트롤러



    OrderController.php
        public function summaryAction(Request $request)
        {
            $orderService = $this->get('OrderService');
    
            $data = [];
            $data['orders'] = $orderService->getSummary();
    
            return $this->render('default/summary.html.twig', $data);
        }
    


    리포지토리



    OrderRepository.php
        public function getSummary()
        {
            $sql =<<<EOQ
    SELECT DATE(created_at) as `date`, COUNT(id) as `count`, SUM(sum) as sum
      FROM orders
     GROUP BY DATE(created_at)
    EOQ;
            $em = $this->getEntityManager();
            $stmt = $em->getConnection()->prepare($sql);
            $stmt->execute();
    
            return $stmt->fetchAll();
        }
    


    서비스



    OrderService.php
        public function getSummary()
        {
            $rawSummaryRows = $this->repository->getSummary();
            $summaryRows = [];
            foreach ($rawSummaryRows as $row) {
                $summary = new OrderSummary();
                $summary->setDate($row['date']);
                $summary->setCount($row['count']);
                $summary->setSum($row['sum']);
    
                $summaryRows[] = $summary;
            }
    
            return $summaryRows;
        }
    


    Entity



    OrderSummary.php
    class OrderSummary
    {
        private $date;
        private $count;
        private $sum;
    
        // :
    }
    


    별해



    View 만들기


    CREATE VIEW order_summaries AS
      SELECT DATE_FORMAT(created_at, '%Y-%m-%d') as `date`, COUNT(*) as `count`, SUM(sum) as sum
        FROM orders
       GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d')
    ;
    

    (주) Doctrine 로 DateTime 형을 ID 로 하려고 하면, DateTime 에 __ToString 의 구현이 필요 같아서 귀찮게 했으므로, 문자열형으로 했습니다.

    샘플 코드



    컨트롤러



    OrderController.php
        public function summaryAction(Request $request)
        {
            $orderService = $this->get('OrderService');
            $repo = $this->get('OrderSummaryRepository');
            $orderService->setSummaryRepository($repo);
    
            $data = [];
            $data['orders'] = $orderService->getSummaryFromView();
    
            return $this->render('default/summary.html.twig', $data);
        }
    


    리포지토리



    OrderSummaryRepository.php
    class OrderSummaryRepository extends \Doctrine\ORM\EntityRepository
    {
    }
    


    서비스



    OrderService.php
        public function getSummaryFromView()
        {
            return $this->summaryRepository->findAll();
        }
    


    Entity



    ViewedOrderSummary.php
    /**
     * ViewedOrderSummary
     *
     * @ORM\Table(name="order_summaries")
     * @ORM\Entity(repositoryClass="AppBundle\Repository\OrderSummaryRepository")
     */
    class ViewedOrderSummary
    {
        /**
         * @var string
         *
         * @ORM\Column(name="date", type="string")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $date;
        /**
         * @var int
         *
         * @ORM\Column(name="count", type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $count;
        /**
         * @var int
         *
         * @ORM\Column(name="sum", type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $sum;
    
        // :
    }
    


    요약


  • 쿼리 결과와 기존 Entity가 일치하지 않으면 일치하는 Entity를 만듭니다.
  • 또는 RDBMS 측에서 VIEW를 만들 수 있습니다.
  • 좋은 웹페이지 즐겨찾기