Sunday, 26 June 2011 21:45
If you don't already know, OpenCart is an open-source e-commerce solution written in PHP that's designed around the MVC paradigm. I've only worked with it briefly, but if you're familiar with other MVC platforms (like Ruby on Rails or CodeIgniter for PHP) then you can find your way around fairly easily.
One thing I would say about OpenCart is that it doesn't have the greatest documentation in the world. Since it is MVC-based you can make up for that loss from your own experience, but still, it's less than ideal. The forums seem pretty active, but they're still no substitute for thorough documentation.
In this tutorial I want to demonstrate how to add a custom catalog (non-admin) view to the many default ones OpenCart comes with. These include (but are not limited to):
Task and assumptions
The view I want to add is a simple one. It displays all the categories with some number of products from each category all on one page. That's a view that OpenCart doesn't come with by default. In OpenCart parlance what we're creating is a new layout.
This really only makes sense with a flat category structure. If you have nested categories it would get unwieldy pretty quickly to display all the categories and their respective products. So I will assume that categories are only one level deep with no children.
I will be demonstrating on a default installation of OpenCart 1.5.0. Before you start, make a copy of the default theme, under /catalog/view/theme/default. I'll call it default-copy.
The place to start is by examining the OpenCart file structure to see where we want to add our modifications. (There are always multiple ways of accomplishing the same task, and this is just one way of doing it. Frankly I haven't explored any others.)
Here's the default OpenCart file structure:
It's fairly self-explanatory. Since we're only adding a new front-end (catalog) view, the catalog folder is the only we're concerned with. That folder looks like:
OpenCart follows an MVC+L design, the L represented by the language folder above. Again, since we're only adding a new layout, we won't be doing anything with the model or language files, so we're only concerned with the controller and view folders.
There are many folders inside /catalog/controller:
Most of these are fairly obvious as to what they pertain to. For instance, account contains controller files relevant to customer accounts, checkout contains controller files relevant to the shopping checkout process, and so on.
We want the controller files that deal with the products on the site. We want to display categories and products, both of which are handled by files in the product folder. The product folder contains:
It may or may not be obvious what these files represent (depending on whether you've worked with MVC-based applications before). Loosely put, each of these files represents a product-related resource users of your site can request. So:
- category.php lets users view products for any given category
- manufacturer.php lets users view products by manufacturer (brand)
- product.php lets users view a single product of interest
- search.php lets users view the products relevant to their search term
We're out to add a new layout (a "type" of view) to the ones already available, so we want to add a new controller file here. I've called it categories.php but you can call it something else if you so desire. Once we're done, categories.php will let users view all the categories of products, with some number of products from each category, like:
- Category One
- Product One
- Product Two
- Product Three
- Category Two
- Product Four
- Product Five
- Product Six
- Category Three
- Product Seven
- Product Eight
- Product Nine
Now the view...
The categories.php controller will retrieve whatever data it requires from the relevant models (which I won't go into) and send them to the appropriate view. View files are held inside /catalog/view, which looks like:
Except for the mail folder, there is a 1-to-1 correspondence between the folders under /catalog/controller and /catalog/view/theme/default-copy/template. It makes intuitive sense that since we added a new controller under /controller/products, we'll add a corresponding view file under /template/products.
The /template/products folder contains the following template files (with the tpl file extension):
Similar to how we added a categories.php controller, we'll add a new view file here (call it categories.tpl), containing the HTML markup and embedded PHP to display the data categories.php is sending it.
We're adding a new controller file and new view/template file for the new view we want to implement:
- We're calling the new controller categories.php and adding it to /catalog/controller/products
- The new view is called categories.tpl and gets added to /catalog/view/theme/default-copy/template/products
Let's move on to the actual contents of the new files.
What we want to display is most similar to what category.php currently does, which is display some number of products for one given category. That seems like a good starting point toward our objective, to display some products from all categories.
For reference, this is the default category.php that comes with the default installation of OpenCart.
Let's look at categories.php, which starts out as a copy of category.php which we modify. I will do this in three steps:
- Irrelevant code blocks commented out
- Irrelevant code blocks deleted
- Relevant code modified and new code added
In the code below, I've commented out blocks of code for the following features, which we don't need for our new view:
- Product sorting, ordering, and pagination
- Breadcrumbs - getting the category title and link, since we're not viewing any single category
- Getting child categories - we're working with a flat category structure
- Category information - name, description, keywords, etc.
- Check for whether a category exists - again, we're not viewing any single category, so no sense in keeping this
It's much easier working with a smaller file with less code, so I've removed all the commented code from the previous step, which is what's shown below.
Now we can look at the full code with modifications and additions.
Lines of note are the following:
Here we specify the number of products we want displayed for each category under limit, which is 3 in this case. We've commented out the sort and order lines because they don't apply in this layout. start will be 0 since there is no pagination in this layout, which is fine for our purpose.
We're adding an element to the $product_data array, which is a product from the category we're currently iterating over. The properties we don't require for this layout have been commented out.
We store the current category as an array element to $this->data['categories']. The products for this category (from $product_data above) are stored as $this->data['categories']['products'].
Similar to how we modeled categories.php from category.php, we'll model categories.tpl from category.tpl.
Here's the default category.tpl view template:
And here's categories.tpl, which derives from it but is a lot shorter, because it:
- Displays less information about the products than the single category view
- Removes the logic to handle child/nested categories
- Shows the products by default (and only) in grid view, and removes the option for switching between list and grid view
I think the code below is pretty straight-forward and self-explanatory. It iterates through all the categories and for each category:
- Displays the category title
- Displays a few products from that category
- Adds a "view more" link to go to the category page
Since we've added a new layout to our OpenCart project, we should add it to the database, which keeps a list of layouts, so we can specify modules that we want to display in our layout.
There are two places to add an entry.
- The first is in the table called layout. Notice the last entry in the screenshot below, which represents the new layout.
- You also need an entry in layout_route, as shown below (the last entry):
Now we can do the following in our OpenCart admin to add a module to the new layout we've created (last entry below):
To create a new layout in an OpenCart 1.5.0.x project that shows a list of all categories and some number of products from each category, follow these steps:
- Add a new controller file to /catalog/controller. I called the file categories.php.
- Copy the contents of category.php which comes with the default theme in OpenCart to the new file (or just copy the file and rename it), and modify it to look like the following:
- Copy the default folder under /catalog/view/theme into a new folder. I called it default-copy.
- Add a new view/template file under /default-copy/template/product called categories.tpl which looks like the following:
- Add an entry for the new layout to the layout and layout_route tables in the OpenCart database so you can add modules to it from within the OpenCart administration panel.
I haven't tried it, but another way to accomplish this same task would be to add a new action to the category.php controller, instead of adding a new controller like I did. Whereas everything is contained in the index action by default, we are free to add a new action with alternative code and corresponding new view.