我的实体中有一个自定义属性:
public function getStockSoldPercentage()
{
return ($this->getStockSold() / $this->getFullStock()) * 100;
}
通过使用此属性,我可以访问库存售罄的百分比。目前我使用的是类似的查询
$bestellers = $this->getDoctrine()->getRepository('CoreBundle:Products')->findAll();
并直接在我的小树枝模板中处理对象(百分比高于例如75%的所有产品)的过滤。所以你看,这在缩放方面不是很好。当我每次用户访问网站时都要查询1000个产品时,这太过分了…
我想构建一个自定义实体存储库,类似于findAllBestSellers()
,只查询getStockSoldPercentage()
属性高于75的所有对象。
我该怎么做?
编辑:
getStockSold()
和getFullStock()
不是字段,而是函数。它们看起来像这样:
public function getFullStock()
{
$stock = 0;
foreach ($this->variants as $variant) {
$stock += $variant->getStock();
}
return $stock;
}
public function getStockSold()
{
return $this->getFullStock() - $this->getCurrentStock();
}
事实上,应用程序逻辑需要太复杂,无法在应用程序中以另一种方式实现。您不能简单地请求SQL中的数据库来获得您想要的内容。
但是,我建议你创建一个sql函数,它会返回你的产品,并在其中记录你的所有逻辑。这将在你的应用服务器上实现负载平衡,mysql的效率要高得多。
之后,您可以通过以下操作调用您的函数:
public function findAllBestSellers() {
$sql = "SELECT PRODUCTS_WITH_STOCK_SOLD_PERCENTAGE() AS products";
$stmt = $this->dbal->executeQuery($sql);
$stmt->execute();
return current($stmt->fetch());
}
解决问题的另一种方法:
//In your controller
$bestsellers = $this->getDoctrine()->getRepository('CoreBundle:Products')->findAll();
$results = [];
foreach ($bestsellers as $bestseller) {
if ($bestseller->getStockSoldPercentage() >= '75') {
$results[] = $bestseller;
}
}
return $this->render('YourTemplate.html.twig', ["results" = > $results]);
这实际上是许多应用程序将具有两个数据库的经典示例。一个用于实时更新,另一个用于报告。
考虑每次出售股票时计算新股票的出售百分比,然后将价值存储在某个地方。这显然会减慢你的个人股票交易速度,但会大大加快你的报告查询速度。这是否是一个可以接受的交易取决于你。
最终,你可以转向一个更基于事件的系统,在这个系统中,出售股票会触发一条消息。一个完全独立的过程会监听这些消息,并相应地更新您的报告表。这将两全其美。