Home Notes Web development OpenCart 1.5.0.x: creating a simple new layout

OpenCart 1.5.0.x: creating a simple new layout E-mail
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):

  • home
  • category
  • product
  • manufacturer

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.

File structure

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:


--- /admin

--- /catalog

--- /download

--- image

--- /system

- .htaccess.txt

- config.php

- index.php

- php.ini


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:


--- /controller

--- /language

--- /model

--- /view


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:


--- /account

--- /affiliate

--- /checkout

--- /common

--- /error

--- /feed

--- /information

--- /module

--- /payment

--- /product

--- /total


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:


- category.php

- compare.php

- manufacturer.php

- product.php

- search.php

- special.php


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:

  1. Category One
    • Product One
    • Product Two
    • Product Three
  2. Category Two
    • Product Four
    • Product Five
    • Product Six
  3. 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:


--- /javascript

--- /theme

------ /default

------ /default-copy

--------- /image

--------- /stylesheet

--------- /template

------------ /account

------------ /affiliate

------------ /checkout

------------ /common

------------ /error

------------ /information

------------ /mail

------------ /module

------------ /payment

------------ /product

------------ /total


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):


- category.tpl

- compare.tpl

- manufacturer_info.tpl

- manufacturer_list.tpl

- product.tpl

- review.tpl

- search.tpl

- special.tpl


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.

categories.php controller

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:

  1. Irrelevant code blocks commented out
  2. Irrelevant code blocks deleted
  3. 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:

Lines 25-31

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.


Lines 68-79

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.


Lines 82-87

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'].

categories.tpl view

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:

  1. Displays less information about the products than the single category view
  2. Removes the logic to handle child/nested categories
  3. 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:

  1. Displays the category title
  2. Displays a few products from that category
  3. Adds a "view more" link to go to the category page

One last thing

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.

  1. The first is in the table called layout.  Notice the last entry in the screenshot below, which represents the new layout.

    OpenCart layout database table


  2. You also need an entry in layout_route, as shown below (the last entry): 

    OpenCart layout_route database table

Now we can do the following in our OpenCart admin to add a module to the new layout we've created (last entry below):

OpenCart admin module page


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:

  1. Add a new controller file to /catalog/controller.  I called the file categories.php.
  2. 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:

  3. Copy the default folder under /catalog/view/theme into a new folder.  I called it default-copy.
  4. Add a new view/template file under /default-copy/template/product called categories.tpl which looks like the following:

  5. 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.

Tags: OpenCart  1.5.x  MVC  PHP  tutorial  view  template  controller  layout