Reputation: 31739
I have a long list of products in my backend (200). Depending if the product is associated to an order or not (someone bought the product), the user will be able to remove it or not from the list. So I have added this line for each product:
{% for subitemColor in subitemsColor %}
...
{% render(controller('ProjectBackendBundle:SubitemColor:checkDeletion'), {'id': subitemColor.id}) %}
...
{% endfor %}
So 200 lines like that are generated. Each of those lines will call this controller.
public function checkDeletionAction(Request $request, $id)
{
$repository = $this->getDoctrine()->getRepository('ProjectBackendBundle:OrderSubitem');
$orders = $repository->findBy(array('subitemColor' => $id));
if (count($orders)) {
return new Response("Product in order");
} else {
return new Response('<a href="' . $this->generateUrl('project_backend_subitem_color_remove', array('id' => $id)) . '">Remove</a>');
}
}
The problem: when the request is thrown, it takes to much time to show the results, maybe two minutes or more.. Is tha normal??
I know I could paginate the list and reduce the time, but I would like let the user to show the 200 results in just one page.
Upvotes: 0
Views: 112
Reputation: 20201
Controller's action code:
public function mainAction(){
$subitemsColor = ...;
$ids = [];
foreach ( $subitemsColor as $color ){
$ids[] = $color->getId();
}
// Populate initial map with all zeros
$countMap = array_values($ids, 0);
/**
* Returns array that look like this:
* {
* {id: id1, cnt: count1},
* {id: id2, cnt: count2},
* ....
* }
*/
$fetchedCountMap = $repository->findOrderCounts($ids);
// Replace "0" with counted value from database
foreach ( $orderCountMap as $count ){
$countMap[$count['id']] = $count['cnt'];
}
return ['subitemsColor' => $subitemsColor, 'orderCountMap': $orderCountMap];
}
Repository method:
public function findOrderCounts(array $ids ){
return $this->getEntityManager()
->createQuery("SELECT id, COUNT(e) AS cnt FROM AcmeBundle:Entity WHERE WHEER e.id IN (:ids)")
->setParameter('ids', $ids);
->getArrayResult();
}
Then it's just a matter of checking orderCountMap
in twig and displaying either link or label if value is 0 or greater.
Upvotes: 0
Reputation: 2175
What I could recommend:
initially retrieve all deletion statuses in primary controller and put in subitemsColor twig variable. Then iterate and use simple if-else clause. In short - move logic from checkDeletionAction()
to twig.
Use Repository as a service and mark it as lazy lazy="true"
COUNT(*)
and use $queryBuilder->getQuery()->getSingleScalarResult()
to avoid full Object Hydration.Upvotes: 1