Installing WordPress on a Mac: the aftermath (phpMyAdmin, databases, themes, plugins and fixing the tags)

Last week I wrote about installing WordPress on a Mac but I wanted to follow that up with a post on what happened next.

Installing phpMyAdmin

Installing WordPress is all very well, but it’s good to be able to manipulate the database. The command line mysql tools would have worked but a graphical interface (even an ugly one with bizarre icons) is often easier, so I installed phpMyAdmin as described by Nino Müller:

  • Download the latest version of phpMyAdmin (I used v3.1.2).
  • Extract the files to ~/Sites/phpmyadmin.
  • Copy config.sample.inc.php to config.inc.php and edit the Blowfish secret (the line which reads $cfg['blowfish_secret'] = ''; .
  • Navigate to http://localhost/~username/phpmyadmin and login.

Unfortunately, after attempting to logon, I was presented with an error message:

#2002 – The server is not responding (or the local MySQL server’s socket is not correctly configured)

Following The Vince Wadhwani’s advice at his Hackido site I typed mysqlconfig --socket to verify the socket is in use for MySQL (e.g. /tmp/mysql.sock) but I couldn’t find a config.default.php file (or the equivalent entry in my config.inc.php file) to adjust the socket. A post at Friends of ED suggested creating a symbolic link for the socket and it seemed to work for me:

sudo mkdir /var/mysql
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock

Following this I could log into phpMyAdmin (although I still have a warning message that phpMyAdmin cannot load the mcrypt extension – this doesn’t seem to be causing any problems though).

Importing a WordPress database

Using phpMyAdmin on my web host’s server, I exported the database from the live copy of markwilson.it and attempted to import it on the Mac. Unfortunately this didn’t work as my database was too large for PHP to upload – as confirmed by creating a file named ~/Sites/phpinfo.php containing <?php phpinfo(); ?>, then viewing it in a browser (http://localhost/~username/phpinfo.php) and looking for the upload_max_filesize variable.

Rather than messing around with my PHP configuration, I googled for the necessary commands and typed:

/user/local/mysql/bin/mysql -u root -p
drop database wordpressdatabasename;
source ./Downloads/wordpressdatabasename.sql
quit

At this point, the local copy of WordPress was running on the live database, but the links were all to the live site, so I used phpMyAdmin to edit the site URL in the wp_options table, changing it from http://www.markwilson.co.uk/blog to http://localhost/~username/blog.

Because the live copy of the site is on an old version of WordPress, browsing to http://localhost/~username/blog/wp-admin prompted me to upgrade the database, after which I could log in and edit the site settings (e.g. the blog address).

WordPress database upgrade

WordPress 2.7 Dashboard

Restoring the theme and plugins

At this point, although WordPress was running on a local copy of my live database, the normal theme was missing and the plugins were disabled (as they were not present). I copied them from the live server and, after selecting the theme and enabling the plugins saw something approaching normality, although there were a few plugins that required updating and I still couldn’t get rid of a particularly annoying database error:

WordPress database error: [Table ‘wordpressdatabasename.wp_categories’ doesn’t exist]
SELECT cat_name FROM wp_categories ORDER BY cat_name ASC

By disabling plugins one by one (I could also have grepped /~Sites/blog/wp-admin/wp-content/plugins for wp_categories), I found that the issue was in the Bad Behavior plugin that I use to ban IP addresses known to send spam.

Moving from categories to tags

When I first moved this site to WordPress, I used Dean Robinson’s Ultimate Category Cloud plugin to provide a tag cloud (at that time WordPress did not support tags). Over time, that because unmanageable and, although I still need to define a decent taxonomy for the site, the categories still have some value if they are converted to tags.

Over some tapas and drinks in the pub, my friend Alex Coles at ascomi and I had a look at the database structure and Alex came up with a quick SQL query to run against my WordPress database:

UPDATE wp_term_taxonomy SET taxonomy='post_tag' WHERE taxonomy='category'

That converted all of my categories to tags, but there were some I manually edited to return to categories (General – which was once called Uncategorised – and Site Notices) but for some reason, all the posts were recorded in a category of Uncatagorized. Some late night PHP coding (reminiscent of many nights at Uni’ – as Steve will no doubt remember – although in those days it was Modula-2, C, C++ and COBOL) resulted in a script to run through the database, identify all posts with a category of 17 (which in my database is the default category of “General”), put the post numbers into an array and then explicitly set the category as required, taking a note of the ones which have been changed so that they can be ignored from that point on:

<html>
<head>
</head>

<body>
<?php

// Connect to the WordPress database
$db_hostname = "localhost:/tmp/mysql.sock";
$db_username = "wordpressuser";
$db_password = "wordpresspassword";
$db_connect = mysql_connect($db_hostname, $db_username, $db_password) or die("Unable to connect to server.");
$db = mysql_select_db("wordpressdatabasename",$db_connect);

// Retrieve all objects including a category with the value of 17 (my default category)
$hascat = mysql_query("SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id = '17' ORDER BY object_id");
echo '<p>'.mysql_num_rows($hascat).' rows found with category</p>';

$correct_ids = array();

// Build a PHP array (not a MySQL array) containing the relevant object IDs for later comparison
while ($row = mysql_fetch_array($hascat))
{
$correct_ids[] = $row[0];
}
echo '<p>Array built. Length is '.count($correct_ids).'. First ID is '.$correct_ids[0].'.</p>';

// Retrieve every object
$result = mysql_query("SELECT * FROM wp_term_relationships ORDER BY object_id");
echo '<p>'.mysql_num_rows($result).' rows found total</p>';

// The magic bit!
// If the object is not in our previous array (i.e. the category is not 17)
// then add it to category 17 and put it in the array so it won't get added repeatedly
while ($row = mysql_fetch_array($result))
{
if (!in_array($row['object_id'],$correct_ids))
{
// Add to category 17
mysql_query("INSERT INTO wp_term_relationships (object_id,term_taxonomy_id,term_order) VALUES ('".$row['object_id']."','17','0')");
echo '<p>Alter database entry for object '.$row['object_id'].'.</p>';
// Add to the array so it is not flagged again
$correct_ids[]=$row['object_id'];
}
else echo '<p style="color:white; background-color:black">'.$row['object_id'].' ignored.</p>';
}

?>
</body>
</html>

Remaining issues

Permalinks don’t seem to work – it seems that Mac OS X does not support using .htaccess files by default and, whilst it’s possible to modify for the root folder it doesn’t seem to work for individual user sites. I’ll do some more digging and see if I can find a fix for that one.

WordPress also features the ability to automatically update plugins (and itself), but my installation is falling back to FTP access when I try to update it and making it work appears to be non-trivial. Again, I’ll take another look when I have more time.

Installing WordPress on a Mac

The software platform which markwilson.it runs on is in desperate need of an updated but there is only me to make it happen (supported by ascomi) and if I make a mistake then it may take some time for me to get the site back online (time which I don’t have!). As a result, I really needed a development version of the site to work with.

I thought that it would also be handy if that development version of the site would run offline – i.e. if it were served from a web server on one of my computers. I could run Windows, IIS (or Apache), MySQL and PHP but as the live site runs on CentOS, Apache, MySQL and PHP it makes sense to at least use something similar and my Mac fits the bill nicely, as a default installation of OS X already includes Apache and PHP.

I should note that there are alternative stacks available for running a web server on a Mac (MAMP and XAMPP are examples); however my machine is not a full web server serving hundreds of users, it’s a development workstation serving one user, so the built in tools should be fine. The rest of this post explains what I did to get WordPress 2.7 up and running on OS X 10.5.5.

  1. Open the System Preferences and select the Sharing pane, then enable Web Access.
  2. Web Sharing in OS X

  3. Test access by browsing to the default Apache website at http://computername/ and a personal site at http://computername/~username/.
  4. Download the latest version of MySQL Community Server (I used mysql-5.1.31-osx10.5-x86_64) and run the corresponding packaged installer (for me that was mysql-5.1.31-osx10.5-x86_64.pkg).
  5. After the MySQL installation is completed, copy MySQL.PreferencePane to /Library/PreferencePanes and verify that it is visible in System Preferences (in the Other group).
  6. MySQL Preferences in OS X

  7. Launch the MySQL preference pane and start MySQL Server (if prompted by the firewall to allow mysqld to allow incoming connections, allow this). Optionally, select automatic startup for MySQL.
  8. MySQL running in OS X

  9. Optionally, add /usr/local/mysql/bin to the path (I didn’t do this, as creating a .profile file containing export PATH="$PATH:/usr/local/mysql/bin" seemed to mess up my path somehow – it just means that I need to specify the full path when running mysql commands) and test access to MySQL by running /usr/local/mysql/bin/mysql.
  10. Enable PHP by editing /etc/apache2/httpd.conf (e.g. by running sudo nano /etc/apache2/httpd.conf) to remove the # in front of LoadModule php5_module libexec/apache2/libphp5.so.
  11. Test the PHP configuration by creating a text file named phpinfo.php containing <?php phpinfo(); ?> and browse to http://localhost/~username/phpinfo.
  12. With Mac OS X, Apache, MySQL and PHP enabled, start to work on the configuration by by running /usr/local/mysql/bin/mysql and entering the following commands to secure MySQL:
    drop database test;
    delete from mysql.user where user = '';
    flush privileges;
    set password for root@localhost = password('{newrootpassword}');
    set password for root@127.0.0.1 = password('{newrootpassword}');
    set password for 'root'@'{hostname}.local' = password('{newrootpassword}');
    quit
  13. Test access to MySQL. using the new password with /usr/local/mysql/bin/mysql -u root -p and entering newrootpassword when prompted.
  14. Whilst still logged in to MySQL, enter the following commands to create a database for WordPress and grant permissions (I’m not convinced that all of these commands are required and I do not know what foo is!):
    create database wpdatabasename;
    grant all privileges on wpdatabasename.* to wpuser@localhost identified by 'foo';
    set password for wpuser@localhost = old_password('wppassword');
    quit
  15. Download the latest version of WordPress and extract it to ~username/Sites/ (i chose to put my copy in a subfolder called blog, as it is on the live site).
  16. Configure WordPress to use the database created earlier by copying wordpressdirectory/wp_config_sample.php to wordpressdirectorywp_config.php and editing the following lines:
    define('DB_NAME', 'wpdatabasename');
    define('DB_USER', 'wpuser');
    define('DB_PASSWORD', 'wppassword');
    define('DB_HOST', 'localhost:/tmp/mysql.sock');
  17. Restart Apache using sudo apachectl restart.
  18. If WordPress is running in it’s own subdirectory, copy wordpressdirectory/index.php and wordpressdirectory/.htaccess to ~/Sites/ and then edit index.php so that WordPress can locate it’s environment and templates (require('./wordpressdirectory/wp-blog-header.php');).
  19. Browse to http://localhost/~username/wordpressdirectory/wp-admin/install.php and follow the “five minute WordPress installation process”.
  20. WordPress installation

  21. After installation, the dashboard for the new WordPress site should be available at http://localhost/~username/wordpressdirectory/wp-admin/.
  22. WordPress fresh out of the box (dashboard)

  23. The site may be accessed at http://localhost/~username/wordpressdirectory/.
  24. WordPress fresh out of the box

Credits

I found the following articles extremely useful whilst I was researching this post:

Installing PHP 5 on IIS 6

I’ve run PHP with Microsoft Internet Information Services (IIS) before (running on a Windows XP laptop) and I seem to remember the installation being quite straightforward. Even so, tonight I was installing PHP 5.2.6 with IIS 6 (on Windows Server 2003 R2 Enterprise x64 Edition) and I ran across a few issues. This post describes what was involved:

  • Firstly, PHP can be installed in CGI, FastCGI or ISAPI mode. I used ISAPI.
  • Secondly, there is anecdotal evidence that the Windows Installer version is problematic – for that reason you may prefer to use the ZIP file and perform a manual installation (as I did), following the instructions on the IIS Admin blog, which were:
    • Extract the files to a location of your choice (I used C:\PHP to keep it simple but C:\Program Files (x86)\PHP would be better).
    • Rename php.ini-recommended to php.ini.
    • Edit the extension_dir line in php.ini to read extension_dir = C:\phpinstallationfolder\ext.
    • Add the PHP installation folder to the %path% system variable (e.g. append ;C:\PHP to the existing path).
    • Create a web service extension for PHP using cscript iisext.vbs /AddFile c:\phpinstallationfolder\php5isapi.dll 1 PHPISAPI 1 “PHP ISAPI”. The new extension should show in IIS Manager with a status of Allowed.
    • Create an application extension mapping for .php files. Following the advice on the IIS Admin blog article that I referenced previously will remove all other mappings so I used the IIS Manager MMC instead (Default Web Site Properties, Home Directory, Configuration to add a mapping to the executable at c:\phpinstallationfolder\php5isapi.dll using extension .php for all verbs).
    • Create a test file called phpinfo.php containing <?php phpinfo(); ?>.
    • Use a web browser to navigate to http://servername/phpinfo.php and the PHP information page should be displayed.
    • If you are running on 64-bit Windows there are some extra steps in order to avoid an HTTP 500 Internal server error or the message %1 is not a valid Win32 application. It seems that this is caused by trying to load a 32-bit application (in this case PHP) inside a 64-bit worker process (as described in Microsoft knowledge base article 895976). To resolve this issue, enter cscript adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 1. adsutil.vbs is one of the scripts installed into the wwwroot\AdminScripts folder but if you have removed it to secure the server (as I had), then it may be temporarily copied back to the server from another IIS installation.
    • To ensure that PHPinfo reflects the correct location of the php.ini file, create an environment variable called PHPRC referring to c:\phpinstallationfolder and restart the server or, alternatively, set the appropriate registry keys (although neither option seemed to have any effect for me).