我有一个实体从REST Web服务中提取数据。为了保持与我的应用程序中从数据库中提取数据的实体一致,我使用了ORM并覆盖了存储库中的查找函数。
我的问题是ORM似乎需要一个数据库表。当我运行doctrine:schema:update
时,它抱怨需要实体的索引,然后当我添加一个索引时,它会为实体创建一个表。我想这将是一个问题,因为ORM将要查询数据库而不是Web服务。
所以......我做错了吗?
1,如果我继续使用ORM,我怎么能让它停止为单个实体需要数据库表。
2,如果我忘记了ORM我在哪里放置数据加载功能?我可以在不使用ORM的情况下将实体连接到存储库吗?
答案 0 :(得分:0)
所以......我做错了吗?
是。如果您不想使用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()
// ...
}
}
或休息客户:
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获取订单,那么仍然可以通过doctrine的延迟加载和事件监听器的帮助来实现。