我可以在不将实体连接到数据库表的情况下使用 ORM
Posted
技术标签:
【中文标题】我可以在不将实体连接到数据库表的情况下使用 ORM【英文标题】:Can I use ORM without connecting entity to a database table 【发布时间】:2015-07-14 09:56:46 【问题描述】:我有一个从 REST Web 服务中提取数据的实体。为了与我的应用程序中从数据库中提取数据的实体保持一致,我使用了 ORM 并覆盖了存储库中的查找函数。
我的问题是 ORM 似乎需要一个数据库表。当我运行doctrine:schema:update
时,它抱怨需要实体的索引,然后当我添加一个索引时,它会为实体创建一个表。我想这将是未来的一个问题,因为 ORM 将要查询数据库而不是 Web 服务。
那么……我做错了吗?
1,如果我继续使用 ORM,我怎样才能让它不再需要单个实体的数据库表。
2,如果我忘记了 ORM,我应该把我的数据加载函数放在哪里?我可以在不使用 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()。如果需要,您仍然可以扩展学说的实体存储库基类,在这种情况下,您需要将它们注册为由工厂创建(学说将是工厂)。或者您可以执行我在答案中提出的操作,仅将实体管理器注入您的存储库。以上是关于我可以在不将实体连接到数据库表的情况下使用 ORM的主要内容,如果未能解决你的问题,请参考以下文章
如何在不将实例模型添加到数据库的情况下向实体模型添加FK约束?
NestJS + MySQL:如何在不设置实体的情况下连接多个数据库
如何在不连接到开放式办公室的情况下查看 .odb 数据库文件的内部?
我可以在不使用 websockets 的情况下使用本机 mqtt 连接到我的 mqtt 代理吗?