symfony2:对嵌入式控制器的多次调用需要花费大量时间

时间:2015-03-18 14:43:27

标签: symfony

我的后端(200)有很多产品清单。根据产品是否与订单相关联(有人购买了产品),用户将能够从列表中删除它。所以我为每个产品添加了这一行:

  {% for subitemColor in subitemsColor %}
   ...
   {%  render(controller('ProjectBackendBundle:SubitemColor:checkDeletion'), {'id': subitemColor.id}) %}
   ...
  {% endfor %}

因此生成了200行。这些行中的每一行都将调用此控制器。

  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>');
      }
  }

问题 :当抛出请求时,显示结果需要花费很多时间,可能需要两分钟或更长时间..是否正常?

我知道我可以对列表进行分页并减少时间,但我希望让用户只在一个页面中显示200个结果。

2 个答案:

答案 0 :(得分:1)

我可以推荐:

  1. 最初检索主控制器中的所有删除状态,并放入subitemsColor twig变量。然后迭代并使用简单的if-else子句。简而言之 - 将逻辑从checkDeletionAction()移动到twig。

  2. 将存储库用作服务并将其标记为惰性lazy="true"

  3. 如果您只需要计算项目数 - 使用COUNT(*)在存储库中创建自己的方法,并使用$queryBuilder->getQuery()->getSingleScalarResult()以避免完全对象水合。

答案 1 :(得分:0)

Controller的操作代码:

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];
}

存储库方法:

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();
}

然后只需检查树枝中的orderCountMap并显示链接或标签,如果值为0或更大。