espier
  • 介绍
  • 技术说明
  • 系统部署
    • 准备工作
      • 域名
      • 七牛
      • 微信开放平台第三方平台申请
      • 域名备案
      • 服务器方案
      • 腾讯位置服务
      • 小程序
      • EcshopX初始化
    • 部署方案
      • 单机部署方案
      • 集群部署方案
  • 框架
    • 文档说明
    • 入门指南
      • 开发环境搭建
        • docker环境
        • 本地环境
      • composer
      • 目录结构
    • 架构思想
      • 中大型项目架构
      • Repository
      • Service
    • Bundle
      • 请求
        • 路由
        • 控制器
      • 数据库
        • 快速入门
        • Repository
        • CRUD Repository
      • 事件系统
      • 消息队列
    • 规范
      • 说明
      • 关于「能愿动词」的使用
      • 代码规范
        • 基本代码规范
        • 编码风格规范
      • Bundle 规范
        • 命名规范
    • 调试
    • 环境变量及配置
  • 快速入门
  • 运维
    • 压力测试报告
      • 5机集群
  • API文档
  • 数据辞典
  • 数据库migration规则
Powered by GitBook
On this page
  • 一、在实体类中添加 repository 类的声明:
  • 二、通过在 repository 类中声明关联的实体

Was this helpful?

  1. 框架
  2. Bundle
  3. 数据库

Repository

在上一章,所有的查询是直接写在你的测试用例的方法中的。但对于程序的组织来说,为了隔离,复用和测试这些查询 Doctrine 提供了一个专门的 repository 类,它允许你保存所有查询逻辑到一个中心位置。

所有的 repository 类,都应该放到 Bundle 的 Repositories 文件夹中。

要定义repository类,有两种方法。

一、在实体类中添加 repository 类的声明:

// src/DemoBundle/Entities/Product.php
<?php
namespace DemoBundle\Entities;

use Doctrine\ORM\Mapping as ORM;
/**
 * @ORM\Entity
 * @ORM\Table(name="products")
 * @ORM\Entity(repositoryClass="DemoBundle\Repositories\ProductRepository")
 */
class Product
{
    //...
}

新建 Repositories 文件夹,在 Repositories 下新建 ProductRepository 类:

//src/DemoBundle/Repositories/ProductRepository.php
<?php
namespace DemoBundle\Repositories;

use Doctrine\ORM\EntityRepository;


class ProductRepository extends EntityRepository
{
    public function findAllOrderedByName()
    {
        return $this->getEntityManager()
            ->createQuery(
                'SELECT p FROM DemoBundle\Entities\Product p ORDER BY p.name ASC'
            )
            ->getResult();
    }
}

在 Repository 类中可以通过 $this->getEntityManager() 方法类获取entity管理。

你就可以像使用默认的方法一样使用这个新定义的方法了:

//src/DemoBundle/Tests/ProductTest.php
/**
 * A basic test example.
 *
 * @return void
 */
public function testProductRepository()
{
    //这一行取出了Doctrine的 entity manager 对象,它负责处理数据库的持久化(写入)和取出对象的过程。
    $em = app('registry')->getManager('default');

    $productRepository = $em->getRepository(Product::class);

    $products = $productRepository->findAllOrderedByName();

    $this->assertEquals(count($productRepository->findAll()), count($products));
}

当使用一个自定义的 repository 类时,你依然可以访问原有的默认查找方法,比如find() 和findAll()等。

使用注解的方式 Doctrine 会在调用 $em->getRepository(Product::class); 时,通过实体的注解找到实体对应的 repository 类。这种方式是 Doctrine 默认提供的,其有一个确定就是:这样定义一个实体只能有一个 repository ,将程序所有自定义查询都放到一个类里面,随着项目的发展,势必会导致 repository 类的肥大。这显然违反 SOLID 的单一职责原则。

二、通过在 repository 类中声明关联的实体

与第一种方法相反,这种方式是通过在 repository 类中声明所关联的实体,来实现 repository 类的声明。由于 repository 类初始化时,需要传入Entity Manager 和实体类的 ClassMate,为了方便初始化 repository 类,需要引入一个 Traits 。

在 Repositories 文件夹下新建一个 ProductPriceRepository 类,用来处理价格相关的查询 :

//src/DemoBundle/Repositories/ProductPriceRepository.php
<?php
namespace DemoBundle\Repositories;

use Doctrine\ORM\EntityRepository;
use EspierBundle\Traits\RepositoryFactory;
use DemoBundle\Entities\Product;

class ProductPriceRepository extends EntityRepository
{
    public static $entityClass = Product::class;

    use RepositoryFactory;

    public function findAllOrderedByName()
    {
        return $this->getEntityManager()
            ->createQuery(
                'SELECT p FROM DemoBundle\Entities\Product p ORDER BY p.name ASC'
            )
            ->getResult();
    }
}

使用方式如下:

//src/DemoBundle/Tests/ProductTest.php

use DemoBundle\Repositories\ProductPriceRepository;

    //...

    public function testProductPriceRepository()
    {
        $productRepository = ProductPriceRepository::instance();

        $products = $productRepository->findAllOrderedByName();

        $this->assertEquals(count($productRepository->findAll()), count($products));
    }
Previous快速入门NextCRUD Repository

Last updated 5 years ago

Was this helpful?