Installing WordPress 2.8 on a Windows server: an anatomy of a web site
- Updated September 16th, 2009 in Technical
- Add a comment
- No comments
The company that hosts my website — CS New Media — provide Linux or Windows hosting. As I’m a developer who works mainly in Microsoft technologies, I’ve opted for the Windows hosting package which also supports ASP.NET 3.5, PHP 5, MS SQL Server and MySQL.
This guide details how I set up Bassett-Jones.com and dealt with any problems along the way. There was a learning curve as I hadn’t much exposure to PHP, but documentation is one of PHP and WordPress‘s strengths.
- Setting up a basic WordPress installation
- Setting user-friendly custom permalinks
- Designing the theme
- Creating custom theme pages
- Getting hugh.bassett-jones.com subdomain to work as a WordPress page
- Installing standard plugins plugins
- Modifying and tweaking plugins
- Writing custom plugins
1. Setting up a basic WordPress installation
Difficulty: 
WordPress’s basic set up and installation is wonderfully simple.
Things to check first with your web host documentation:
- How to create a database and database user. My web host uses the Helm control panel which includes a database manager.
- How to copy files to your web server. This is usually done through an FTP client such as FileZilla.
- Make sure PHP is running using a test.php file with
<?php phpinfo() ?>
Following the Famous 5-Minute Installation Guide
- Create a database and database user e.g.
wordpress1andwordpress1user - Download the latest version of WordPress and unzip
- Rename the
wp-config-sample.phpfile towp-config.php. - Edit the following lines in the newly renamed
wp-config.php./** The name of the database for WordPress */ define('DB_NAME', 'wordpress1'); /** MySQL database username */ define('DB_USER', 'wordpress1user'); /** MySQL database password */ define('DB_PASSWORD', 'userpassword'); /** MySQL hostname */ define('DB_HOST', 'mysql5.webhost.com'); - Copy all the files to your web server
- Visit the start page to complete the installation
2. Setting user-friendly custom permalinks
Difficulty: 
Windows 2003 and IIS 6 do not include URL rewriting and so cannot map a page such as www.bassett-jones.com/?page_id=9 to the more friendly www.bassett-jones.com/hugh/ in the same way that Apache does using mod_rewrite.
If your web host supports custom error pages, you can use this to create user-friendly custom permalinks.
Request -> Status 404 Not Found -> wp-404-handler.php -> Status 200 Success
- Create a new page called
wp-404-handler.php - Add the following code
<?php $_SERVER['REQUEST_URI'] = substr($_SERVER['QUERY_STRING'], strpos($_SERVER['QUERY_STRING'], ':80')+3); $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI']; include('index.php'); ?> - Upload
wp-404-handler.phpto your web server - Set your custom error page to point to
wp-404-handler.php. View instructions for Helm control panel. - I like the web site addresses in the format www.bassett-jones.com/post-title/, so from the WordPress Dashboad go to Settings > Permalinks > Common Settings > Custom Structure and set to
/%postname%/.
Note that once this is done, the page at the custom permalink will not accept any forms with a method of post. This means that some of the plugins break and may need tweaking as detailed in 7. Modifying and tweaking plugins.
3. Designing the theme
Difficulty: 
I already had an idea how I wanted the site to look based on the previous version. Sketching out the design in Balsamiq Mockups showed the main areas of the two different types of pages — one for entries, and one for pages such as Search, About and Tags.


The Template Hierarchy and default theme give a breakdown and example of how to construct a custom theme. My post page design fitted into the standard Header → Content → Sidebar → Footer theme design.
To manage the different styles between post-type pages and standard pages, I created two styles sheets style.css and page.css. The header.php then includes either one depending on the type of page:
<?php if (is_page() || is_404() || is_search() || is_archive() ) { ?>
<link rel="stylesheet" href="<?php bloginfo('template_directory') ?>/page.css" type="text/css" media="screen" />
<?php } else { ?>
<link rel="stylesheet" href="<?php bloginfo('stylesheet_url') ?>" type="text/css" media="screen" />
<?php } ?>
The sidebar blocks 3 – 7 are automatically handled through the administration interface and sidebar.php by using:
<?php dynamic_sidebar() ?>
4. Creating custom theme pages
Difficulty: 
My theme required separate pages for About, All, Contact, Hugh, Random, Search, and Tags. About, Contact and Hugh could use the standard template, while the rest would need a custom theme page each. codex.wordpress.org/Creating_a_Search_Page details the steps of how to create a search page using a custom template file. The other pages were created in a similar way.
- Create a new page template
- On the edit page dashboard option, choose the template file to use
All pages and posts
<?php
/*
Template Name: All
*/
?>
...
<?php query_posts('orderby=post_modified&order=desc'); ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="post">
<h2 id="post-<?php the_ID(); ?>"><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>
...
</div>
<?php endwhile; endif; ?>
<?php $pages = get_pages('orderby=post_modified&order=desc'); ?>
<?php foreach ($pages as $page) { ?>
<div class="page">
<h2><a href="<?php echo get_page_link($page->ID) ?>"><?php echo ucfirst($page->post_title) ?></a></h2>
...
</div>
<?php } ?>
Go to a random page
<?php
/*
Template Name: Random
*/
?>
<?php
$rand = new WP_Query();
$rand->query('showposts=1&orderby=rand');
while ($rand->have_posts()) : $rand->the_post();
$location = "Location: " . get_permalink();
endwhile;
header($location,true,302);
?>
Search site
<?php /* Template Name: Search */ ?> <?php get_header(); ?> <div id="main"> <h1>Search Bassett-Jones.com</h1> <?php get_search_form() ?> </div> <?php get_footer(); ?>
Tag cloud
<?php /* Template Name: Tags */ ?> <?php get_header(); ?> <div id="main"> <h1>Tags o' plenty</h1> <?php wp_tag_cloud(); ?> </div> <?php get_footer(); ?>
5. Getting hugh.bassett-jones.com subdomain to work as a WordPress page
Difficulty: 
WordPress is installed on www.bassett-jones.com, but I like the style of hugh.bassett-jones.com instead of www.bassett-jones.com/hugh/. My web host sets up subdomains to map to a sub folder of the main domain. This means that hugh.bassett-jones.com needs to map to a file that exists at www.bassett-jones.com/hugh/index.php.
This page /hugh/index.php then retrieves the real page content.
<?php
if($_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"] == "www.bassett-jones.com/hugh/") {
header("Location: http://hugh.bassett-jones.com",true,301);
exit;
}
echo file_get_contents('http://www.bassett-jones.com/?page_id=9');
?>
The above code checks if www.bassett-jones.com/hugh/ is being requested, and if so permanently redirects to hugh.bassett-jones.com. It then retrieve the Hugh page using the hard-coded page_id, as /hugh/ would continually loop.
6. Installing standard plugins plugins
Difficulty: 
These are the plugins that required no modification and extend the standard WordPress installation. They were installed using the Dashboard Plugins Installation and Widget Panel.
Akismet Checks comments against the Akismet web service to see if they look like spam or not and reduces the amount of unwanted comments.
flickrRSS Integrates photos from the flickr RSS and allows you to specify the template HTML.
Google XML Sitemaps Automatically generate a sitemaps.org compatible site map for search engines to find content.
Raw HTML capability On a per-post basis, disable the automatic html conversion of the WordPress rich text editor. Useful for posts with with code in them.
WordPress.com stats Simple visitor tracking and analysis.
WP-Memory-Usage Shows the current memory usage and limit on the Dashboard.
7. Modifying and tweaking plugins
Difficulty: 
Tiny Contact Form
By default, Tiny Contact Form has an empty form action that POSTs the contact data back to the page that it is currently on (around line 76 in tiny-contact-form.php).
<form action="" method="post">
This does not work with 2. Setting user-friendly custom permalinks, as only GET actions are supported. I modified the action to post to the underlying page address instead:
<form action="' . get_bloginfo("url") . '/?page_id=' . get_the_ID() . '" method="post">
Commenting on pages does not need a similar modification, as the comment form POSTs to wp-comments-post.php.
WPtouch iPhone Theme
WPtouch is an excellent plugin that formats the content of the web site when accessing from an iphone or similar mobile device.
Version 1.9 does not support skins, so any modifications will be overwritten with updates, but it looks like 2.0 will support them.
I’ve edited the bottom of header.php to include a brief intro about me on every page.
<div id="hugh" style="position: relative; -webkit-border-radius: 8px;">
<img style="width: 100%; display: block;" src="<?php bloginfo('wpurl'); ?>/wp-content/themes/hugh/images/hughmini.jpg" alt="Hugh"/>
<h2 style="position: absolute;"><a href="http://hugh.bassett-jones.com">Hi, I'm Hugh.</a></h2><p>Cheerful husband and developer based in Hampshire, UK <a href="http://hugh.bassett-jones.com">Read more …</a></p>
</div>
8. Writing custom plugins
Difficulty: 
I had a clear idea of how I wanted the theme to look and what the html produced needed to be.
Some plugins such as flickrRSS allow template html to be used for each item, but others did not quite fit what I needed.
Recent Tweets, YouTube Videos, and Xbox Games all follow the basic pattern of retrieving an XML document from another location, parsing and extracting relevant data into html before storing and displaying on the page.
To reduce the number of times the page requests data from the external sites, I cache the html in the database and only request new data once every 24 hours.








