【问题标题】:Can I use ORM without connecting entity to a database table我可以在不将实体连接到数据库表的情况下使用 ORM
【发布时间】:2015-07-14 09:56:46
【问题描述】:

我有一个从 REST Web 服务中提取数据的实体。为了与我的应用程序中从数据库中提取数据的实体保持一致,我使用了 ORM 并覆盖了存储库中的查找函数。

我的问题是 ORM 似乎需要一个数据库表。当我运行doctrine:schema:update 时,它抱怨需要实体的索引,然后当我添加一个索引时,它会为实体创建一个表。我想这将是未来的一个问题,因为 ORM 将要查询数据库而不是 Web 服务。

那么……我做错了吗?

1,如果我继续使用 ORM,我怎样才能让它不再需要单个实体的数据库表。

2,如果我忘记了 ORM,我应该把我的数据加载函数放在哪里?我可以在不使用 ORM 的情况下将实体连接到存储库吗?

【问题讨论】:

    标签: entity-framework symfony orm doctrine-orm


    【解决方案1】:

    那么……我做错了吗?

    是的。如果您真的不想使用 ORM,那么使用 ORM 接口是没有意义的。

    我认为最好的方法是根本不考虑实现细节。为存储库引入您自己的接口:

    interface Products
    {
        /**
         * @param string $slug
         *
         * @return Product[]
         */
        public function findBySlug($slug);
    }
    
    interface Orders
    {
        /**
         * @param Product $product
         * 
         * @return Order[]
         */
        public function findProductOrders(Product $product);
    }
    

    并使用 ORM 实现它们:

    class DoctrineProducts implements Products
    {
        private $em;
    
        public function __construct(EntityManager $em)
        {
            $this->em = $em;
        }
    
        public function findBySlug($slug)
        {
            return $this->em->createQueryBuilder()
               ->select()
               // ...
        }
    }
    

    或 Rest 客户端:

    class RestOrders implements Orders
    {
        private $httpClient;
    
        public function __construct(HttpClient $httpClient)
        {
            $this->httpClient = $httpClient;
        }
    
        public function findProductOrders(Product $product)
        {
            $orders = $this->httpClient->get(sprintf('/product/%d/orders', $product->getId()));
    
            $orders = $this->hydrateResponseToOrdersInSomeWay($orders);
    
            return $orders;
        }
    }
    

    您甚至可以让一些方法使用 http 客户端,而另一些则使用单个存储库中的数据库。

    将您的存储库注册为服务并使用它们,而不是直接调用Doctrine::getRepository()

    services:
        repository.orders:
            class: DoctrineOrders
            arguments:
                - @doctrine.orm.entity_manager
    

    始终依赖于您的存储库接口,而不是特定的实现。换句话说,始终使用存储库接口类型提示:

    class DefaultController
    {
        private $orders;
    
        public function __construct(Orders $orders)
        {
            $this->orders = $orders;
        }
    
        public function indexAction(Product $product)
        {
            $orders = $this->orders->findProductOrders($product);
    
            // ...
        }
    }
    

    如果您不将控制器注册为服务:

    class DefaultController extends Controller
    {
        public function indexAction(Product $product)
        {
            $orders = $this->get('repository.orders')->findProductOrders($product);
    
            // ...
        }
    }
    

    这种方法的一个巨大优势是您可以随时更改实现细节。 mysql 搜索不够好?让我们使用弹性搜索,它只是一个存储库!

    如果您需要调用 $product->getOrders() 并在后台从 API 获取订单,在学说的延迟加载和事件侦听器的帮助下应该仍然可以。

    【讨论】:

    • 因此工作的 MVC,RestOrders 和 DoctrineProducts 类是存储库,与我已经编写的用于覆盖 ORM 函数的存储库相同。我只需要根据需要包含并创建它们,而不是使用 $em->getRepository() 函数来加载它们。 Order 实体不需要知道它是由 RestOrders 存储库管理的。对吗?
    • 是的,将您的存储库注册为服务并使用它们而不是 Doctrine::getRepository()。如果需要,您仍然可以扩展学说的实体存储库基类,在这种情况下,您需要将它们注册为由工厂创建(学说将是工厂)。或者您可以执行我在答案中提出的操作,仅将实体管理器注入您的存储库。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多