【问题标题】:How to improve getTotalProducts on Opencart controllers如何改进 Opencart 控制器上的 getTotalProducts
【发布时间】:2013-09-01 00:58:53
【问题描述】:

我以前不知道,但是 Opencart 官方版本中有一个巨大的错误,在一个商店里,当你有很多产品和类别时,它需要 50 秒!!!加载页面。 50秒!!! ,我查看了代码和谷歌,发现问题有据可查,因为几乎每个人都知道这条线导致了一切。 (从缓存中计数)

$product_total = $this->model_catalog_product->getTotalProducts($data);

每个地方都发布的解决方案包括注释掉这一行,顺便说一句,如果我将 $product_total 设置为空,至少对我来说效果更好。像这样

//$product_total = $this->model_catalog_product->getTotalProducts($data);

                $product_total = "";

无论如何我的问题已经解决了(页面加载在 3 秒内而不是 50 秒内)但是计数丢失了所以我一直在寻找,最后我发现这个解决方案非常多,(直到现在,仍在测试)最好的解决方案如果您的数据库正在处理大量产品和类别..http://ergopho.be/speeding-up-opencart-using-the-cache-class/

它所做的基本上是将整个代码段包装在一个 if 块中,并首先检查该文件是否存在于缓存中。如果没有,我们像往常一样运行它,然后将其存储到缓存中。如果是这样,请改用缓存版本。

在 Controller/Common/Header.php 中,您还可以找到此代码(在他对类别进行的文章中)这里也是此文件中的代码

$this->data['categories'] = array();

$categories = $this->model_catalog_category->getCategories(0);



        foreach ($categories as $category) {

            if ($category['top']) {

                // Level 2

                $children_data = array();



                $children = $this->model_catalog_category->getCategories($category['category_id']);



                foreach ($children as $child) {

                    $data = array(

                        'filter_category_id'  => $child['category_id'],

                        'filter_sub_category' => true

                    );



    $product_total = $this->model_catalog_product->getTotalProducts($data);


                    $children_data[] = array(

                        'name'  => $child['name'] . ($this->config->get('config_product_count') ? ' (' . $product_total . ')' : ''),

                        'href'  => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id'])

                    );                      

                }


Yo have to wrap all this code into this lines

$this->data['categories'] = $this->cache->get('categories');
if(!count($this->data['categories'])) { 

<!--Here goes the above code-->

$this->cache->set('categories', $this->data['categories']);
}

到目前为止它工作正常,我希望这对其他人有所帮助,还请注意,如果你有更好的方法来做到这一点,我知道有很多非高级用户正在寻找这个,所以如果你可以分享和我们一起,那就太好了。

¿ 谁能为这个可怕的缓慢错误找到更好的解决方案?

感谢并希望在 Opencart 的下一个版本中解决此类问题。

希望这会有所帮助。和平

【问题讨论】:

    标签: php performance caching opencart


    【解决方案1】:

    这确实应该进入模型而不是控制器。

    我有一个拥有超过 15,000 种有效产品的网站。我的方法是这样的:

    public function getTotalProducts($data = array()) {
        if ($this->customer->isLogged()):
            $customer_group_id = $this->customer->getCustomerGroupId();
        else:
            $customer_group_id = $this->config->get('config_customer_group_id');
        endif;  
    
        $sql = "SELECT COUNT(DISTINCT p.product_id) AS total"; 
    
        if (!empty($data['filter_category_id'])):
            if (!empty($data['filter_sub_category'])):
                $sql .= " FROM {$this->prefix}category_path cp 
                          LEFT JOIN {$this->prefix}product_to_category p2c 
                            ON (cp.category_id = p2c.category_id)";         
            else:
                $sql .= " FROM {$this->prefix}product_to_category p2c";
            endif;
    
            if (!empty($data['filter_filter'])):
                $sql .= " LEFT JOIN {$this->prefix}product_filter pf 
                            ON (p2c.product_id = pf.product_id) 
                          LEFT JOIN {$this->prefix}product p 
                            ON (pf.product_id = p.product_id)";
            else:
                $sql .= " LEFT JOIN {$this->prefix}product p 
                            ON (p2c.product_id = p.product_id)";
            endif;
        else:
            $sql .= " FROM {$this->prefix}product p";
        endif;
    
        $sql .= " LEFT JOIN {$this->prefix}product_description pd 
                    ON (p.product_id = pd.product_id) 
                  LEFT JOIN {$this->prefix}product_to_store p2s 
                    ON (p.product_id = p2s.product_id) 
                  WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' 
                  AND p.status = '1' 
                  AND p.date_available <= NOW() 
                  AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";
    
        if (!empty($data['filter_category_id'])):
            if (!empty($data['filter_sub_category'])):
                $sql .= " AND cp.path_id = '" . (int)$data['filter_category_id'] . "'"; 
            else:
                $sql .= " AND p2c.category_id = '" . (int)$data['filter_category_id'] . "'";            
            endif;  
    
            if (!empty($data['filter_filter'])):
                $implode = array();
    
                $filters = explode(',', $data['filter_filter']);
    
                foreach ($filters as $filter_id):
                    $implode[] = (int)$filter_id;
                endforeach;
    
                $sql .= " AND pf.filter_id IN (" . implode(',', $implode) . ")";                
            endif;
        endif;
    
        if (!empty($data['filter_name']) || !empty($data['filter_tag'])):
            $sql .= " AND (";
    
            if (!empty($data['filter_name'])):
                $implode = array();
    
                $words = explode(' ', trim(preg_replace('/\s\s+/', ' ', $data['filter_name'])));
    
                foreach ($words as $word):
                    $implode[] = "pd.name LIKE '%" . $this->db->escape($word) . "%'";
                endforeach;
    
                if ($implode):
                    $sql .= " " . implode(" AND ", $implode) . "";
                endif;
    
                if (!empty($data['filter_description'])):
                    $sql .= " OR pd.description LIKE '%" . $this->db->escape($data['filter_name']) . "%'";
                endif;
            endif;
    
            if (!empty($data['filter_name']) && !empty($data['filter_tag'])):
                $sql .= " OR ";
            endif;
    
            if (!empty($data['filter_tag'])):
                $sql .= "pd.tag LIKE '%" . $this->db->escape(utf8_strtolower($data['filter_tag'])) . "%'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.model) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.sku) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.upc) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.ean) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.jan) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.isbn) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            if (!empty($data['filter_name'])):
                $sql .= " OR LCASE(p.mpn) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
            endif;
    
            $sql .= ")";                
        endif;
    
        if (!empty($data['filter_manufacturer_id'])):
            $sql .= " AND p.manufacturer_id = '" . (int)$data['filter_manufacturer_id'] . "'";
        endif;
    
        $cache = md5 ((int)$customer_group_id . serialize ($data));
    
        $total = $this->cache->get('product.total.products.' . $cache);
    
        if (!$total):
    
            $query = $this->db->query($sql);
            $total = $query->row['total'];
    
            $this->cache->set('product.total.products.' . $cache, $total);
    
        endif;
    
        return $total;
    }
    

    您会注意到靠近末尾的缓存部分。

    我还转换为 memcached 来缓存查询结果,而不是文件缓存。当您将 seo_urls 用于这么多产品时,真正的问题出现了,我不得不完全重写整个 SeoUrl 控制器和 Url 库,但它很快而且我有很棒的 url :)

    【讨论】:

    • 我认为是 Seo Url ,你改变了什么?谢谢,我测试了你的模组,但它的速度太慢了
    • 就像我说的,我有 15000 多种产品,而且非常快。对于 SeoUrls,我做了一个完整的重写以添加所有关键字和路由的缓存,这非常复杂但效果很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多