我之前不知道,但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能够解决这类问题。
希望这会有所帮助。和平
答案 0 :(得分: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 Controller和Url库,但它很快,而且我有很棒的网址:)