Posts and Pages Tagged ‘opencart’

Opencart – ‘The Twig_Autoloader class is deprecated…’ error Last updated:4 May 2022

I was contacted by a client last week who was getting this error message on her site.

It appears on Opencart 3.x up to 3.0.3.5, and is caused by an older version of the Twig template engine not playing nicely with PHP 8. Thus the problem often occurs if your hosting company has upgraded your PHP version without telling you. Searching for the error mainly finds a number of sites with the same issue, plus a number of threads on the (sadly rather unhelpful and not uncommonly abusive) Opencart forums, none of which have what I think is a clear answer. So, for the benefit of others, here are your options if this happens to you:

Update your Opencart version

This is the best option. Upgrading from 3.x to a newer version is relatively straightforward and documented elsewhere.

Revert to an earlier version of PHP

This is good for a quick fix, and is generally done from your hosting Control Panel. If your hosting provides cPanel, then it’s accessed via MultiPHPManager. Find the affected domain, and change the PHP version from 8 to 7.4. Apply the change and your errors should have disappeared.

To restate, this is just a temporary fix as at some point in the future your hosting company may remove the option to run PHP7.

Manually update files on the server

At this point all the purists will be throwing their hands in the air and listing lots of reasons why this is bad idea. However, we live in the real world, and it may be you have multiple hard coded customisations on your install, and you really don’t want to take any risks. If this is the case, read on, this is what I did:

  1. Take whatever backups of your filesystem and database you need to sleep soundly
  2. Download a copy for the latest Opencart (3.0.3.8 at the time of writing) to your PC
  3. From your new download, upload the whole of the system folder on top of your current version.
  4. Similarly, upload the catalog/controller/event/theme.php file on top of your current version
  5. If you currently have your storage folder outside your Opencart directory, edit config.php and admin/config.php to set the storage folder back to ...system/storage withhin your Opencart directory

And that’s it. You’ll want to run your own checks of course, but that worked for me.

Opencart will prompt your to move your storage folder when you log in to admin.

If for whatever reason you haven’t uploaded the system folder on top of the existing one, but deleted the old one instead, then you will get a different error complaining about Openbay. This is because Openbay support was removed in OC3.0.3.6. Assuming you don’t need this then find this line in both catalog/controller/startup/startup.php and admin/controller/startup/startup.php:

registry->set(‘openbay’, new Openbay($this->registry));

and delete it or comment it out.

Loading Instagram posts on your website – using Powershell with cURL Last updated:28 April 2022

Spent some time yesterday including Instagram posts on one of my websites (this one if you’re interested). In order to get this going you need to use cURL, run from a command line, which was new to me. Windows 10 and later allows you to do this from Powershell, but I had to mess around a bit before it works, so here goes if anyone else needs this.

To start off you need to create an Instagram App. The Instagram instructions here are fine, so I won’t go through that.

My trouble started at Step 5 – ‘Exchange the Code for a Token’. Instagram gives this example code:

curl -X POST \
  http://api.instagram.com/oauth/access_token \
  -F client_id=684477648739411 \
  -F client_secret=eb8c7... \
  -F grant_type=authorization_code \
  -F redirect_uri=http://yoursite.com/auth/ \
  -F code=AQDp3TtBQQ...

…but this needs amending to use in Powershell, to:

curl.exe  '-X'  'POST' 'http://api.instagram.com/oauth/access_token' '-F' 'client_id=684477648739411' '-F' 'client_secret=eb8c713c492d1f9c19d7120e94ffcb205' '-F' 'grant_type=authorization_code' '-F' 'redirect_uri=http://www.yoursite.com/' '-F' 'code=AQDp3TtBQQh297S2as5YbDNAU9h3772mvryptCeWWT28z-Xadqq4YfA_YiGXui-cNnLjT7Wg_mrC0OAe0Q5l5x1RvdMarGvFIC1fv7I_kz32oGfKn-R1YlTEyLnPCKksGHeVgw7aJ3iLgXaS8QB9q-WNdG8PiWICz5Icwb4XULBNXs9DONlkIA1i94lNXoKsnkbLL13aMJLGpiiMksitRuZSRblwKrI1dEi7xqeHPcd9VJQ'

This took me about an hour to work out… Similarly, the request for a long-lived token needs to be formatted like this:

curl.exe '-i' '-X' 'GET' 'http://graph.instagram.com/access_token?grant_type=ig_exchange_token&client_secret=eb8c713c492d1f9c19d7120e94ffcb205&access_token=IGQVJYclF4WUllREZABbU9rWm1TS2F0am12cWRUVWxIbURLQXc2eXZAyaTVmNnU5a0ZAFTlU4bkFCOG5sd0JwWFMwZA0VYR0ZAFcnVBZAzZAoVFFwdVN5bmVaWmNGQm42X3VvSEJNc0ZAfWG1zbjB3OThFbm9SNk1wZAHZArOVJVQnQw'

Once you’ve got the access token then you’re off and running. I was using PHP to call the Instagram data from Opencart, so I created a custom module, stored the access token as an Opencart setting and included this code to call Instagram (in a model file, called by the module controller):

	public function getInstagramContents() {
		$fields = "media_type,media_url,permalink,thumbnail_url";//call the fields you want
		$token = $this->config->get('instagram_access_token');//get the stored token
		$limit = 4;//get the four most recent posts
		 
		$json_feed_url="http://graph.instagram.com/me/media?fields={$fields}&access_token={$token}&limit={$limit}";
		$json_feed = @file_get_contents($json_feed_url);
		$contents = json_decode($json_feed, true, 512, JSON_BIGINT_AS_STRING);
		
		return $contents;
	}

If you’ve got this far you’re probably OK with the restof it, but if the rest of the Opencart stuff is useful let me know in the contents below.

Opencart unable to access admin after updating Last updated:13 June 2018

Spent this morning updating a client’s site to Opencart 1.5.6.4. All went well until I tried to log in to admin, when the admin login screen just refreshed, no error message, nothing in error log. After some digging, I identified that although the site was ussing SSL, the form was being submitted to a non-SSL URL. So it failed. The solution was to edit the admin config.php file to set the HTTP_SERVER constant to use https.

define('HTTP_SERVER', 'http://yourdomain.com/admin/');

There are lots of mutterings on various boards about this, but didn’t see this as a solution…Hope it helps.

Opencart – Setting up multiple stores Last updated:6 February 2018

Here’s how to set up multiple stores on Opencart using subdomains. You could use this to set up a separate store to run a different theme – although this is not essential – you can run several stores with the same theme if you want.

The steps will vary depending upon your version of Opencart.

Opencart 1.5.x

Create your subdomain

Let’s assume you’re running your main store on www.yourshop.com, and that your web hosting locates the files for your store in its root directory public_html. For a mobile store, let’s also assume you’re going to sit this on m.yourshop.com.

You need to create your new domain and point it at the same folder that your main store uses. If your hosting uses cPanel then it should look something like this:

Screenshot of additional domain in cPanel

Create your new store

The next step is to create the new store in Opencart. Go to System > Settings and click the ‘Insert’ button. This should bring up screens to create your new store. For the Store URL and SSL URL, enter your new domain, adding https to the SSL URL if you have a certificate installed. Make sure you close your entries with a ‘/’ or it won’t work. Fill out the rest of the details on the General tab, and your screen should look something like this:

Screenshot of Opencart store configuration screen

Now the Store tab. Here you need to enter the store name, and select the theme you want to use (e.g. a mobile theme). Set the default layout to ‘Default’. Your screen should look something like this:

Screenshot of Opencart store configuration screen

You can then save your new store.

Configure your new store

Opencart will create your new store with all the default settings, so you will need to amend all the store settings as required.

Opencart will not load any categories, products, manufacturers or information pages to your new store (unfortunately?). You’ll need to do all these manually, or by running some SQL queries from the backend. To do this manually:

  • Categories – From the Category edit screen, go to Data > Stores to mark the checkbox against your new store.
  • Products – From the Product edit screen, go to Links > Stores to mark the checkbox against your new store.
  • Manufacturers – From the Manufacturer edit screen, mark the checkbox against your new store.
  • Information – From the Information edit screen, go to Data > Stores to mark the checkbox against your new store.

Modules in your new store – using Layouts

If you’re using Opencart 1.5.x, then any Modules that you have configured will not be carried over to your new store. Opencart manages the display of extensions by using the concept of Layouts – which is a little tricky to grasp, I think.

A Layout is the entity which links Modules to pages and stores. When a page is to be displayed on a store, Opencart looks up the layout appropriate to that page on that store, and then finds any modules configured for that layout.

So, if you make no changes to any Layouts after creating your new store, then when a page on your new store is displayed, Opencart will search for the appropriate Layout, and not find one. It will therefore use the Default layout which we assigned when the store was set up. This (probably) has no Modules assigned to it, and so no Modules will be displayed. So, to display a Module on your new store, we need to configure a Layout.

I’ll illustrate this with an example. Let’s assume you have some Modules on your default store homepage, and you want to display the same Modules on your new store. First thing is to navigate to System > Design > Layouts and click ‘Edit’ against the ‘Home’ Layout. You should then see something like this:

Screenshot of Opencart store configuration screen

You’ll see that the existing (default) entry tells Opencart that for the default store the Layout ‘Home’ should be used with the route, or page ‘common/home’ – which is the home page. We need to tell Opencart to use the same Layout for the new store. So, click ‘Add Route’, select the new store and enter ‘common/home’ against the route – like this:

Screenshot of Opencart store configuration screen

Click ‘Save’ and you’re done.

You can probably see from this that it’s possible to display different modules on your new store homepage by creating a new Layout and assigning it to your new store only. Here’s some more details on how to do this.

You’re done

Once this is complete, your new store should display via the subdomain, with the products etc and modules that you have enabled in the steps above. Payment, Shipping and Order Totals will all be the same as your existing store.

Opencart 2.x and 3.x

Create your subdomain

For my example, I’m assuming a store running on www.yourstore.com, with its root directory public_html. For a substore, let’s also assume you’re going to sit this on trade.yourshop.com.

You need to create your new domain and point it at the same folder that your main store uses. If your hosting uses cPanel then it should look something like this:

Screenshot of additional domain in cPanel

Create your new store

The next step is to create the new store in Opencart. Go to System > Settings – which shows Stores – and click the blue ‘+’ button. This should bring up screens to create your new store. For the Store URL and SSL URL, enter your new domain, adding https to the SSL URL if you have a certificate installed. Make sure you close your entries with a ‘/’ or it won’t work. Fill out the rest of the details on the General tab, and your screen should look something like this:

Screenshot of Opencart store configuration screen

Now the Store tab. Here you need to enter the store name, and select the theme you want to use (YooBlue in my example). Set the default layout to ‘Default’. Your screen should look something like this:

Screenshot of Opencart store configuration screen

You can then save your new store.

Configure your new store

Opencart will create your new store with all the default settings, so you will need to amend all the store settings as required.

Opencart will not load any categories, products, manufacturers or information pages to your new store (unfortunately?). You’ll need to do all these manually, or by running some SQL queries from the backend. To do this manually:

  • Categories – From the Category edit screen, go to Data > Stores to mark the checkbox against your new store.
  • Products – From the Product edit screen, go to Links > Stores to mark the checkbox against your new store.
  • Manufacturers – From the Manufacturer edit screen, mark the checkbox against your new store.
  • Information – From the Information edit screen, go to Data > Stores to mark the checkbox against your new store.

Modules in your new store – using Layouts

If you’re using Opencart 2.x or later, when you create a your new store, all the Modules that you have configured will automatically be carried over to your new store (note this is different to 1.5.x).

Opencart manages the display of extensions by using the concept of Layouts. A Layout is the entity which links Modules to pages and stores. When a page is to be displayed on a store, Opencart looks up the Layout appropriate to that page on that store, and then finds any Modules configured for that Layout. You can find Layouts under Design > Layouts. If you edit the Home Layout you should see something like this:

Screenshot of Opencart store configuration screen

You’ll see that the first entry tells Opencart that the ‘Home’ Layout applies to the default store when the route, or page ‘common/home’ is displayed – the home page. When we created our second store Opencart duplicates this for use, so the ‘Home’ layout also applies to our new store when the route ‘common/home’ is used. Result – the Modules assigned to the Layout ‘Home’ are displayed on both the default and trade store.

You can probably see from this that it’s possible to display different modules on your new store homepage by creating a new Layout and assigning it to your new store only. Here’s some more details on how to do this.

You’re done

Once this is complete, your new store should display via the subdomain, with the products etc and modules that you have enabled in the steps above. Payment, Shipping and Order Totals will all be the same as your existing store.

Opencart – implementing a mobile theme Last updated:15 June 2015

There’s a number of approaches to implementing a mobile theme on Opencart. First off, let’s assume that you’re not just catering for mobiles, and that you want to make different pages available to mobiles.

Option 1 – Use a single responsive theme

In theory it’s possible to serve a single theme which will adapt itself to the screen size used via css media queries. Originally, this approach required too many compromises to result in a good experience all round. Media queries mean that you’re just displaying the page differently, but the html served to the page is identical, and hence there’s no way to avoid serving lots of big images to a mobile (or conversely, serving poor quality images to a desktop browser). With improved mobile networks, this is far less of an issue, and this is now my preferred approach. (The BBC, currently, are serving low quality images and then using js to add better quality images dependent on screen size, resulting in a horrible experience on a desktop. Hum.)

Option 2 – Create a separate store that uses a mobile specific theme

Once you take this step (instructions here) then there are again some options as to how this is implemented. For the purposes of this document I’ll assume a main store set up on http://www.mystore.com and a mobile store on http://m.mystore.com. The mobile store has id=1 within Opencart.

Option 2A – Detect the mobile browser using PHP

There are a number of mobile browser detect scripts out there. These attempt to identify a browser as coming from a mobile from the header information passed from the browser when it calls the page. I tried using the Mobile Detect class. This is simple to use. I stored the Mobile_Detect.php file in the root of my store, and included the following code (in red_ in catalog/controller/common/home.php:

class ControllerCommonHome extends Controller {
	public function index() {
	
		include $_SERVER['DOCUMENT_ROOT'].'/Mobile_Detect.php';
		$detect = new Mobile_Detect();
		if ($detect->isMobile() && !$detect->isTablet() && $this->config->get('config_store_id')!=1){
			header('Location: http://m.mystore.com');
		}	
	
		$this->document->setTitle($this->config->get('config_title'));

So, I’m calling the Mobile_Detect() class, and from the results of that, if it’s a mobile, and if it’s not a tablet, and if it’s not already the mobile store (identified by store_id = 1 here, check your own installation), then I’m redirecting to the mobile store homepage.

This works fine, and redirects all calls to the default store homepage only from a mobile (phone) to the mobile store. You could use similar code in catalog/controller/common/header.php to redirect any page to its mobile equivalent. Something like:

class ControllerCommonHeader extends Controller {
	protected function index() {
	
		include $_SERVER['DOCUMENT_ROOT'].'/Mobile_Detect.php';
		$detect = new Mobile_Detect();
		
		if ($detect->isMobile() && !$detect->isTablet() && $this->config->get('config_store_id')!=1){
			if (isset($this->request->server['HTTPS'])) {
				$mobile_redirect = 'http://m.mystore.com';
			} else {
				$mobile_redirect = 'http://m.mystore.com';
			}
			if ($_SERVER['REQUEST_URI']) $mobile_redirect .= html_entity_decode($_SERVER['REQUEST_URI']);
			header('Location: '.$mobile_redirect);
		}		
			
		$this->data['title'] = $this->document->getTitle();

Here I need to additionally construct the URL to redirect to from the entered URL. I’ve tested this across a number of pages, both with and without SEO URLs, and it seems to work fine. I don’t have access to a test server with SSL enabled, however, so be warned…

A potential issue here is that the customer doesn’t really know what’s happened to them, and worse, they can’t get back to the main store, because they’ll always be redirected. The other downside is that the redirect itself relies on accurately detecting the device from the headers. A glance at the code in Mobile_Detect.php reveals a whole list of device identifiers that is going to become outdated at some point, leading to incomplete redirections. While it’s quite neat (at least at the moment), I’m not keen on the inflexibility.

Option 2B – Detect the mobile browser using javascript

It would be possible to detect the screen width of the browser, and redirect to your mobile store if the width is less than a certain value. If you just want to implement this on your home page, then it’s quite simple – just add the following to your default store home.tpl:

<script type="text/javascript">
if (screen.width <= 699) {
window.location('http://m.oc1531.simonbattersby.com');
}
</script>

If you want to redirect every page it get's messy, and it's easier I think to do some of the work in the controller - you could add the following to catalog/controller/common/header.php:

		if (isset($this->request->server['HTTPS'])) {
			$mobile_redirect = 'http://m.mystore.com';
		} else {
			$mobile_redirect = 'http://m.oc1531.simonbattersby.com';
		}
		if ($_SERVER['PHP_SELF']) $mobile_redirect .= $_SERVER['PHP_SELF'];
		if  ($_SERVER['QUERY_STRING']) $mobile_redirect .= '?'.html_entity_decode($_SERVER['QUERY_STRING']);
		$this->data['mobile_redirect'] = $mobile_redirect;

This is using the same logic to build the redirect URL as above. Then, in your default store header.tpl:

<script type="text/javascript">
if (screen.width <= 699) {
window.location='<?php echo $mobile_redirect;?>';
}
</script>

Using javascript has the advantage that you're just relying on the screen's width, and hence are not dependent on any list of browsers being kept up to date. I'm still not keen on the inflexibility however...

Option 2C - Let the customer choose

You could just let the customer choose which version they want to use...they'll always know if they're using a mobile or not (hopefully).

One way of doing this is to use Opencart's Store module, which will list all your stores and let the customer navigate from one to the other from a drop down menu. You could also just add a manual link (by editing header.tpl) to point at your mobile store.