Open cart actually has a built-in caching class, although it does not use it everywhere that it should. It’s quite easy to carry out, and when used appropriately, you should see some pretty major speed gains (On sites with very large databases anyway).

The caching opencart uses is pretty simple, it basically takes some information (usually an array, but potentially anything), serialises it and sticks it in a file. This allows us to cut down on the number of database queries we are running as we can just check if someone else has run the same query in the last hour, if they have, we just give them the stored results. The best time to use the caching is to store results of any query that runs on a very regular basis and is likely to return the same results now as it will in an hours time. For the example below I will use the category module (Which displays the categories in the sidebar).

/system/library/cache.php contains 4 relevant methods

The constructor basically works as a cleanup function, it checks the cache directory (/system/cache) for any cached information that’s more than an hour old, and if it finds anything, it deletes it. This keeps your information relevant. This runs automatically.

The get function is very simple. $this->cache->get(‘CACHED_ITEM_NAME’); This will return either the cached information (if it exists) or nothing.

The set function stores information in the cache. $this->cache->set(‘CACHED_ITEM_NAME’, ‘CACHED_ITEM_VALUE’);

And finally, the delete function : $this->cache->delete(‘CACHED_ITEM_NAME’); removes the item from the cache (This is handy if you want to avoid having to wait an hour for the cache to expire after changing things like category order in the backend.

Let’s take a look at our file (I am working with 1.5.1.3.1) open up catalog/controller/module/category.php, it’s a pretty simple controller, all it does is runs through the categories and sticks them in an array. The view file then sticks them into the sidebar. This block of code, which runs multiple SQL queries (depending on how nested your categories are) starts at line 29

<?php
$this->data[categories] = array();

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

foreach ($categories as $category) {
	$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(
			category_id => $child[category_id],
			name        => $child[name] .  ( . $product_total . ),
			href        => $this->url->link(product/category, path= . $category[category_id] . _ . $child[category_id])	
		);					
	}


	$data = array(
		filter_category_id  => $category[category_id],
		filter_sub_category => true	
	);		

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

	$this->data[categories][] = array(
		category_id => $category[category_id],
		name        => $category[name] .  ( . $product_total . ),
		children    => $children_data,
		href        => $this->url->link(product/category, path= . $category[category_id])
	);

}
?>

We can fix this with just a couple of lines of code

<?php
$this->data[categories] = $this->cache->get(categories);

if(!count($this->data[categories])) {
	$this->data[categories] = array();
	$categories = $this->model_catalog_category->getCategories(0);

	foreach ($categories as $category) {
		$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(
				category_id => $child[category_id],
				name        => $child[name] .  ( . $product_total . ),
				href        => $this->url->link(product/category, path= . $category[category_id] . _ . $child[category_id])	
			);					
		}

		$data = array(
			filter_category_id  => $category[category_id],
			filter_sub_category => true	
		);		

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

		$this->data[categories][] = array(
			category_id => $category[category_id],
			name        => $category[name] .  ( . $product_total . ),
			children    => $children_data,
			href        => $this->url->link(product/category, path= . $category[category_id])
		);
	}
	$this->cache->set(categories, $this->data[categories]);

}
?>

All we are doing here is wrapping this entire section of code in an if block, and first checking if the file exists in the cache. If it does not, we run it like normal, and then store it to the cache. If it does, use the cached version instead. Simple as that, and you can use it anywhere that requires it with just a few lines of code.

Ian McCarthy

A 30 something year old Irish developer

killarneyman
killarneyman


Published