WordPress – Zen Cart integration
Introduction
WordPress is an extremely powerful open source blogging package. Not only it is free, it has a vibrant community of users and plug-in developers.
Zen Cart is an open source shopping cart. Due to its flexible template system it is shaping up to overtake most other non-commercial carts.
I use WordPress as a micro-CMS.
Unfortunately, there is no fully functional WordPress shopping cart plug-in. Yes, there are several projects in development, often much friendlier than Zen Cart or OS Commerce, but also buggy and immature.
Since both WordPress and Zen Cart are nicely striuctured and written in PHP, they should work together, right? In fact, there is even an existing Zen Cart module for integrating the two.
If you are just looking for a good general approach / laundry list of issues to consider in a similar project, read this excellent post and download this PDF.
Implemented on
- Zen Cart 1.3.7
- WordPress 2.0
The Challenge
The existing integration has some important limitations:
- it is poorly documented (NOT the author’s fault, English is not his native language),
- it requires Zen Cart and WordPress to be installed into the root of the site in one ugly pile
- it also seems to see Zen Cart as the main front-end package with WordPress being mostly a back-end bloggin engine.
- it requires (minor) changes to be made to the core WordPress code
What I want:
- avoid changes to application core if at all possible
- keep WordPress as the main engine for the site,
- seemlessly transfer visitors to Zen Cart when needed
- maintain consistent look and feel across these two applications
- minimise duplication: any change should be made in one place only. (having to remember to make the same changes in different places on two different packages is a recipe for guaranteed disaster)
Now, this is a tall order, so I am going to relax the rules a bit:
There is no requirement to integrate each and every feature of Zen Cart – just the ones I need. I’ll leave the rest to people with more spare time.
The plan
- Install Zen Cart and WordPress into separate directories under root (wordpress is still the site’s main CMS).
- Make WordPress built-in functions available in Zen Cart templates.
- Integrate WordPress header, footer, and style.css with those of Zen Cart.
- There is NO requirement to make Zen Cart functions available inside WordPress.
Hopefully, this will result in a common look and feel: same colors, fonts, header, footer. The header should contain the main menu thus providing seamless navigation across the two applications.
The easy part – installing the module
There is an existing integration module available here and here. Since it comes all the way from Japan, the documentation is a bit sparce and the support is less than perfect. Come on! Give the guy a break! – English is not his native language, and the support is free, so don’t you dare whine! Just be thankful he shared. BTW, Thank you, Hira!
I started by installing (uploading) the module including to the instructions. Sort of. I did less:
- My WordPress and my Zen Cart reside in separate directories despite the recommendation in the module readme
- I did not make the changes to
wp-include/template-loader.php
. I do not understand potential impact of this move, but os far nothing broke. If it does, I will post it here.
The hard part: wordpress in its own directory
includes/extra-configures/wordpress.php
supplied in the integration package seemed to contain a copy of the standard wordpress configuration files. The problem with having a copy is that when (not if) you change the originals you got to remember to change the copy as well.
You cannot just incude them though – wp-config.php relies on its location to set up ABSPATH. No worries. I defined ABSPATH in wordpress-config.php
!
Here is what it boiled down to:
define (‘ABSPATH’,’/var/www/vhosts/staging/wordpress/’);
$woz_install=0;
if (file_exists(ABSPATH.’wp-settings.php’)) {
$woz_install=1;
define(‘WP_USE_THEMES’, true);
$wp_did_header = true;
include (ABSPATH.’wp-config.php’);
define (‘SHOP_URL’,get_bloginfo(‘siteurl’).’/wherever-your-shop-appears-to-be/’);
/* this SHOP_URL definition is NOT strictly necessary, but I found this definition useful when hacking various Zen Cart templates and modules, since my shop’s “front page” is actually a WordPress page. For example, in PayPal Express I changed the Cancel_Url to take the user to the shop’s front page, not to the login page. Once again, you do NOT need this definition */
$i=strlen(DIR_WS_CATALOG);
$req=substr($_SERVER[‘REQUEST_URI’],$i,1);
if($req==’?’){
$_GET[‘main_page’]=’wordpress’;
}
if(isset($_GET[‘feed’])){
wp();
gzip_compression();
require_once(ABSPATH.’/wp-includes/template-loader.php’);
exit();
}
}
This is all I have in my wordpress-config.php
and it seems to be enough. It’s all php, I am just too lazy to figure out how to mention it in a post without the blog filtering out the invocation. Sorry. I am sure you can figure out what needs to be added at the begining and the end of this file. Or let me know how to put it in here!
Just remember to input your own wordpress location into the ABSPATH definition at the beginning instead of my fictitious one.
The styles
This is probably the easiest part of them all. All I want is to include my WordPress stylesheet inthe pages generated by Zen Cart (and pray the style names do not clash and override each other). Guess what, Zen Cart automatically loads any styleXXXX.css file that you put into your Zen Cart includes/templates/your-template-name/css
directory.
No need to copy anything either. Just go there and issues ln
command like this: ln full-path-to-your-style.css
There may be a more elegant way of doing this. By putting some smart code into html_header.php you will guarantee that you get the right style.css even when you switch themes. Me, I do not expect to be switching themes any time soon, and if I do more things will break than I can possiby imagine anyway. I know it’s wrong, but given the choice between a perfect implementation and writing al this down… i chose.
The footer
Zen Cart footer is generated by tpl_footer.php template . The original copy resides in Zen Cart’s includes/templates/template_default/common
directory. It is strongly recommended that you let it be, and use the template override system. Just create a new template (if you have not done so already) and copy the file into it. THEN edit it.
The original tpl_footer.php contains a lot of code. Most of it deals with features that can be switched on or off via the admin UI, so I’d recommend that you leave them untouched.
The two pices I I chose to comment out are:
- A line of code within – it seemed to be a navigation aid not managed by an “
if
“ - Zen Cart Copyright notice. Important: according to Zen Cart you can only do this legally if you choose not to use any images that came with your Zen Cart. According to my research, you do not need to display the © symbol for your content to be protected (like we do not put “do not steal” labels on everything). But then I am not a lawyer.
Now, simply including my wordpress footer into Zen Cart footer seemed a bit naive, since, for example, Zen Cart does not generate tag in its template footer. It does it elsewhere. What other useful functions does it perform in the process? – I dunno. So, a bit more finesse is called for.
My WordPress footer contains two kinds of stuff:
- footer conent: the things I want to show to the visitors like the copyright notice, some links, some stats, etc.
- closing tags for a bunch of styles (opened in my wordpress header), and
So, I created wp-footer-content.php and wp-footer-divs.php in my wordpress theme directory. Footer content went into one,
tags into the other. The new footer.php has two php includes and looks like this:
include 'wp-footer-content.php';
wp_footer();
include 'wp-footer-divs.php';
As far as WordPress is concerned, nothing has changed.
Meanwhile, my Zen Cart’s tpl_footer.php now has two more php includes closer to the end:
include TEMPLATEPATH.'/wp-footer-content.php';
include TEMPLATEPATH.'/wp-footer-divs.php';
Note 1: pick the placement of these lines carefully: virtually all of Zen Cart footer is incapsulated in a conditional statement that allows to switch the footer off via the admin UI. You decide if you want to retain that feature or ignore it. Retain? – put your lines inside the conditional. Ignore? – stick them at the very end.
Note 2: since I integrated the footer before the header, I did not want my wp-footer-divs.php to accidentally close the wrong divs, so I commented it out for a while (till I had the header set up). If you are doing this all in one go and have good attention to detail, you may get away with having one wp-footer-xx instead of two. It’s a personal choice.
Note3: notice how wp_footer() ends up not being invoked by Zen Cart. It is a personal choice, but in my case it was important because among other things it calls up Google Analytics for me, thus adding a call to a non-secure site and scaring visitors away from the shopping cart (most people freak out when they get “the site contains a mix of secure and non-secure elements” message). Yes, there is a way to call Google Analytics securely (I wrote apost about it recently), but there are challenges there as well.
The header
Zen Cart header is split between html_header.php
and tpl_header.php
html_header.php
contains everything your visitors will never see: all the header and meta tags, all stylesheet and javascript references, all the “service” stuff. WordPress does not have an elegant way of including javascrip into the templates. If you have any and it is generated by some plug-in… I have no advice for you.
If you have put some javascript into the header.php yourself… pull it into a separate php file, put an appropriate include
into your header.php
and then create a link to it in includes/templates/YOURTEMPLATE/jscript
directory.
tpl_header.php
is where the visible header is generated. Just like in the footer, most functions are controlled via Zen Cart admin interface, so you do not have to delete/comment out much.
If you follow same procedure I suggested for the footer, remember that wp-header-divs.php
goes first – we are opening them, right? 😉
I put my includes
include TEMPLATEPATH.'/wp-header-divs.php';
include TEMPLATEPATH.'/wp-header-content.php';
at the very beginning, above all other HTML, for the sake of simplicity. Otherwise there is a danger that you’d miss something and end up with weirdly overlapping styles that will take forever to trace down.
The default template starts with the “header alert” mechanism… Whether your wordpress header goes above or below it is your choice.
Very important! Do use Zen Cart’s template override system. It will save you a suicide when you loose all your changes duting the next upgrade.
Caching ( read this !! )
If you have WP-Cache enabled in Wordpres, you MUST make sure that it does NOT cache your Zen Cart pages.
If you forget, you will notice that when you start changing product quantity in the cart, some times it will change, and other times it won’t. My (and yours) gratitude goes to Ryan (see his comments below) for finding the bug and reporting it.
The fix is simple:
- Look up the name of your cart’s directory. It is usually “catalog”, or “shop” (in my case it’s “eshop”). You can often find it in your URL. It is also specified in your includes/configure.php file as ‘DIR_WS_CATALOG’ (ignore the slashes for the next step).
- In your WordPress admin menu go to Options -> WP-Cache and input the name of your cart’s directory (in my case “eshop”) into the “Rejected URIs” box.
- Click “SAVE” and you are done.
Native Zen Cart caching works fine (I use the ‘file’ option).
eAccelerator
eAccelerator works perfectly in my setup and required zero configuration out of the box. It cut my page serve times by about 70%. I love it!
I have not used APC (Advanced PHP Cache) with either WordPress or Zen Cart, so I have no idea how it will behave.
Easy Ordering from WordPress
If you are interested integrating these two wonderful applications, it’s probably because you mention the products from your Zen Cart store in your WordPress blog. Wouldn’t it be nice to be able to put a “Buy Now” button into the relevant blog posts and pages?
An amazingly useful Zen Cart contribution “Quick Order” can be found here. Once you install it (just unzip according to the instructions), you can easily create links that will instantly insert a product (or even several products) into user’s shoppinc cart.
The products are identified by their Zen Cart part numbers (so you do ot want any duplicates there), and the links can be placed anywhere.
I love this! If only now there was a way to easily pull product’s current price and put it next to the link…
OOPS! – “Quick Order” does not handle Zen Cart product attributes. What does it mean? – If you have a product that must be sold with at least some attribute (like, say, color), you got a problem. In my case, I cannot sell downloadable products, since downlads are implemented via attributes.
Now, if you are just selling products (or services), you can probably do without any attributes whatsoever, and everything will be fine.
The site has gone live
My integration efforts have been rolled into production.Most of the site is actually wordpress. To see Zen Cart you hot to travel to one of the product pages (still WordPress) and click “Add To Cart” or “View Cart” and you will be majically transformed into Zen Cart universe. The easiest way to notice the border is by looking at the URLs: wordpress has nice permalinks, while Zen Cart… is necessarily different.
120 Comments
Jump to comment form | comment rss [?] | trackback uri [?]