I have a custom property in my entity:
public function getStockSoldPercentage()
{
return ($this->getStockSold() / $this->getFullStock()) * 100;
}
By using this property, I can access the percentage of stock sold out. At the moment I use a query like this
$bestellers = $this->getDoctrine()->getRepository('CoreBundle:Products')->findAll();
and handle the filtering of the objects (all products with a percentage above e.g. 75%) directly in my twig template. So you see, this isn't really good regarding scaling. When I have to query 1000 products each time a user visits the website, is overkill…
I want to build a custom entity repository, something like findAllBestSellers()
and just query all objects whose getStockSoldPercentage()
property is higher than 75.
How can I do this?
getStockSold()
and getFullStock()
are not fields, but functions. They look like this:
public function getFullStock()
{
$stock = 0;
foreach ($this->variants as $variant) {
$stock += $variant->getStock();
}
return $stock;
}
public function getStockSold()
{
return $this->getFullStock() - $this->getCurrentStock();
}
In fact, you've applicative logic needs too complex to do it in another way inside your application. You can't simply request your database in SQL to get what you want.
BUT, I advise you to create an sql function which is returning your products and transcript all your logic in it. That will load balance the charge on your applicative server and mysql is far more efficient to do it.
After that, you can call your function by doing :
public function findAllBestSellers() {
$sql = "SELECT PRODUCTS_WITH_STOCK_SOLD_PERCENTAGE() AS products";
$stmt = $this->dbal->executeQuery($sql);
$stmt->execute();
return current($stmt->fetch());
}
A different approach to solve your problem:
//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]);
This is actually classic example of why many applications will have two databases. One is for real time updates and the second is for reporting.
Consider calculating the new stock sold percentage each time a stock is sold and then storing the value someplace. This would obviously slow down your individual stock transaction but speed your reporting queries up considerably. Deciding if that is an acceptable trade off is up to you.
Eventually you could move to a more event based system in which selling a stock would trigger a message. A completely independent process would listen for these messages and update your reporting tables accordingly. Which would give the best of both worlds.