Last time I showed you how to create a simple events listing using perhaps the most powerful feature of WordPress 3.0 – custom post types. After some requests to develop this further, today we’ll be creating a product review database to tie together everything we’ve learnt so far.
You’ll be able to maintain a separate list of products using custom post types, each with an associated image, as well as some meta-info such as price, rating, specifications – and we’ll finish it all off with a way to display them in a sidebar widget and an index page.Sounds good? Read on.
Requirements:
You’ll need a working WordPress 3.0+ self hosted install, and this will make use of extensive PHP coding. I’ll give you the code, but you’ll need to be relatively comfortable with PHP and XHTML to adjust variable names to your needs or change the style. If you need a quick beginners course on CSS and XHTML, may I suggest our wonderful free beginners guide to download. I’d also suggest you use a cleanly coded but basic theme – the default Twenty-Ten or Twenty-Eleven theme is actually quite complicated to edit, so try this first on something simpler before trying to integrate with that.
Create Post Types
If you read last weeks tutorial, you should be somewhat familiar with creating a custom post type in WordPress. Copy and paste this base code into a new plugin, activate it, and begin adding some new products so we have a dataset to work with. (Note: If you’d rather just download the complete and full code now without trying to add things along the way, use this finished code instead. You can still follow along with the tutorial and customize it as we go)

It’s also wise to decide now what kind of meta-info you want to associate with each product. A database of digital cameras for instance might need:
- Retail Price
- Resolution
- HD Video
- Purchase Link
- Rating
Rather than adding this info directly to the description of the product (the ‘post content’), we’re going to create custom fields to hold this info. On the add product screen, make sure you’ve enabled custom fields, then create a new field for each info set. You’ll only need to create new fields once – the next product you add you’ll be able to select the name of the custom field from the drop down box. Don’t forget to add a featured image, as well be using this to display alongside the info product later on.
Single Product Template
If you try to view one of your products now, you’ll probably get a 404 – Not Found error. To fix that, head into the permalinks settings of WordPress and just hit Save Settings once. Now when you view one of your new product entries, depending on your theme, you might see something a little plain. The title and description text are there, but what about all our custom meta info and the image?
To customize the single product views, we’ll need to customize a new template file called single-products.php – do this by duplicating your existing single.php so we have the groundwork in place and aren’t starting from scratch.

At this point, I’m going to make a very small change to the line that displays “Written by (author) on (date)”, so instead it just reads “Added to the database on (date)”. This is just so I can be sure template is working, and refreshing the single product page should show this change instantly.
Now, to add the featured post image we attached to the product, this one line should do it (I included style info too, in case you need it). I’ve posted the full code to my own single-products.php here, but remember it’s unique to my theme so simply copying that into your own theme directory may produce unexpected results.
![]()
The simplest way to add the meta info anywhere is to use:
![]()
…but this will only give us a very basic output list of key-value pairs. In order to do anything more complicated with the returned values (such as display a star-rating graphic), you need to grab all the values then iterate over them. [View the code here]:

In the example above, I’m checking each custom field name (the $key) to see if it’s called ‘Level’. If it is called level, instead of just echoing the value of the field back, I’m displaying a different graphical element based on the content. For any other custom fields, I’m echoing the value as it is, along with the name of the field (which is exactly what the_meta() does). Now my single product page looks like this:

I’m going to leave it there for single product views, as it really depends upon your own theme and what you want to achieve with it. For now, let’s move onto a sidebar widget to display… the 3 highest ranked products in the database?
Widget
To do this, I’ve slightly adjusted the code I gave you before in the post How to Write a Basic WordPress Widget, but instead of showing a single random post, I’ve adjusted it with the following [view the full code here]:

This will give me 3 posts laid out similar to the example screenshot below. If you’re not seeing any of your products displayed, check very carefully the section that says &meta_key=Rating to make sure you actually have a meta key of that name. Notice how I also chose to display the meta info associated with that product along with the featured thumbnail, but you can edit that particular code block to show whatever you like.

Product Archives or Listing
Finally, I also wanted to make an index/archives page, so that visiting http://yourdomain.com/products/ would show a simple list of all the products, similar to a blog index. The basic excerpt + post thumbnails style I showed you how to make in the How To Add Post Thumbnails To Your Theme article was mostly sufficient, but in order to customize it I duplicated the archive.php file in my theme and renamed it archive-products.php.
If you don’t already have an archives page, just duplicate index.php and rename it to archive-products.php. Again, by adjusting the article meta-info line and adding a call to the the_meta() somewhere, I got this:

Obviously, it looks a bit silly with both the archives and sidebar, and it could do with a bit more style adjustment, but I’ll leave that up to you!
That’s it from me today. You can view the complete full code online here – just copy and paste or download the entire thing into a file called products.php, and place it in your plugins directory. You should be able to potentially expand your WordPress blog into a database of anything now! It’s difficult to answer individual problems you might be having, but do please post in the comments if you’d like some help or would like to show your appreciation – a tweet or Facebook like would very much be appreciated, or even a mention on your blog if you decide to implement this. Thanks for reading, and don’t forget all the other WordPress tutorials we have!
MakeUseOf Recommends
More articles about:
Hide 13 Comments
Thanks a lot for your tutorials. They’re great and I’m learning a lot.
I want to implement this with my jazz cd collection but I have a question: I already have a database with tones of data about every cd (including songs, musicians,…). My database is made usung Filemaker. Is there a way to import that data to WordPress?
If the answer is no, i’ll asume I’ll have to do all the work with the 400 cd…
Thanks in advance.
Álex. http://jazztk.com
Thanks for the compliment Alex, feedback always appreciated.
I was all ready to say no, but then came across this: http://wordpressfilemaker.com/
Supposedly, it will sync your filemaker with WP, creating posts or pages. Now , there are few issues here I think, but none that can’t be overcome. Mainly, if you want to work with custom post types as this tutorial shows, you may need to find another plugin that lets you convert posts -> custom types, though I’m pretty sure one exists. If not, you can always jump into the db and do a mass find a replace (make sure you import them into a specific category , then just change all the records for that category to type whatever instead of post). Definintely do-able!
Excellent tutorial. Reminds me i need to add reviews to my website asap.
Thanks this is great. I was having problems with the archive order but then I found this: http://wordpress.org/extend/plugins/post-types-order/
Do you know of a simple hack to display the product archive in date order (newest to oldest) without such a plugin? The default seemed to be oldest to newest which is not the same as regular posts.
Thanks.
Hi MissBossy! Glad you appreciate the tutorial.
If you’re okay with editing templates, just change the archive-products.php and just before the if (have_posts()) : bit, add this
global $query_string;
query_posts( $query_string . ‘&order=DESC’ );
That should work ;) Basically, you’re customizing the query string used to make a call to the database. I’m not sure why it’s defaulting to an ascending date order though.
Yes! That did the trick. Thanks for being so responsive.
Thanks for the tutorial! Love it.
-Andy
http://www.ventme.com/
Nice plugin, Always wonder how to do this.
I copied and pasted complete full code into a plugin. I can see the Products Tab, only thing is when I add a new product/post I can’t see my custom fields, checked the screen options and its not there either. I have also got all in one seo plugin installed, which i can see in my normally new post window.I am using Custom Field templete plugin too, but i am guessing if they are all working in the normally new post that fault is not really with them. Any suggestions
Hmm, custom fields are definitely enabled in the code, so I suspect there might be a conflict with the template plugin thing. AIO SEO should be fine though – try disabling the custom field template and see if they appear then.
By the by… I tweaked your code to include excerpts – this gives me a bit more flexibility with archive descriptions.
Anyone who wants to do this just change
‘supports’ => array(‘thumbnail’,'custom-fields’,'title’,'editor’,'comments’)
for
‘supports’ => array(‘thumbnail’,'custom-fields’,'title’,'editor’,'excerpt’,'comments’)
And with the Custom Field Template plugin, it’s possible to build something that can be handed over to less tech savvy users. This opens up a lot of possibilities.
So thanks again for this code. I’m having fun with it.
Love your plugin, but I have a question?
How can I change the permalink structure? If I change the slug it still uses the rest of my permalink structure (looks like this: wordpress.url/blog/products/productname-date/).
I want something like wordpress.url/products/productname without changing my structure cause I need it for the rest of the page. Any suggestions?
Hi Sebastian. I think this code should do the trick:
‘rewrite’ => array( ‘slug’ => ‘film’, ‘with_front’ => false )that should be placed inside the array section of the register post type function. Let me know if you dont know what that means and ill try to paste a full snippet from teh original code. Also, you’ll need to re-save your permalink structure settings to make it kick into effect.
Works perfectly. Thx :)