Prevent WordPress from guessing if users hit a 404 error

WordPress has a feature called Canonical Redirects which attempts to make sure that users always end up on the one true URL for a given request. That’s great for SEO. Built in to this feature, however, is something that mystifies a lot of developers: when a user reaches a 404, WordPress will use some fuzzy matching try to guess what they meant and redirect them.

To me, this is pretty much the polar opposite of a canonical redirect. I’d much rather have 404s result in a helpful 404 page which I can track in analytics. It can also be very confusing when you’re trying to add your own rewrite rules to WordPress.

Fortunately, you can filter the Canonical Redirect to prevent this strange 404 behavior. Add this to functions.php in your theme:

function stop_404_guessing($url) {
	if (is_404()) { return false; }
	return $url;
}
add_filter('redirect_canonical', 'stop_404_guessing');

Now WordPress will continue redirecting to the canonical URL, unless you hit a 404 in which case it will display your 404 page as expected.

Posting some WordPress tips at the day job

During the week I work at a Vermont-based web agency called Union Street Media, where I’m fortunate to spend every day working with a great team on WordPress-powered websites. I’m going to start posting some of the things you’d usually expect to see here at scottnelle.com on the company blog. It will mostly be tips that I uncover during the work day after failing to find a good solution via Google. The first of these posts covers adding content to the end of all posts of a specific type. I’ve used that technique to build a plugin which allows our project managers to create project milestone signoff forms directly on the site.

Stay tuned for more WordPress posts from me both here on scottnelle.com and over at the USM Interactive Blog.

Connecting Slim Framework and MySQL

Slim Framework is a very light PHP framework that’s great for building web applications and REST APIs. The Slim Hello World example, found right on the homepage, will get you up and running in a matter of minutes. Once you’ve done that, the next step is to create a template and use it to display data from a database. Read on to find out how.

Database

We’ll create a very simple database to get our data from. It will have a single table, “friends,” which contains three fields: id, name, and job. Here’s the SQL for that table:

CREATE TABLE `friends` (
   `id` int(10) unsigned not null auto_increment,
   `name` varchar(255),
   `job` varchar(255),
   PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4;

INSERT INTO `friends` (`id`, `name`, `job`) VALUES 
('1', 'Sam', 'Gardener'),
('2', 'Molly', 'Chef'),
('3', 'Evan', 'Web Developer');

Database connection

Slim doesn’t come with a database connection utility of its own. You can use any database connection toolkit you like. If you have a favorite, use it!. We’ll be using the MySQLi object, which is the modern way to connect to a MySQL database in native PHP. Put the following code in index.php or stash it in another file and include that file in index.php. In my case I’ve put it in a file at lib/mysql.php.

function connect_db() {
	$server = 'localhost'; // this may be an ip address instead
	$user = 'user';
	$pass = 'pass';
	$database = 'slim_db';
	$connection = new mysqli($server, $user, $pass, $database);

	return $connection;
}

Getting the data

Index.php is the main controller for your application. If you set up the Hello World example you’ve already used it to route requests, accept variables through the URL, and return data. Now we’ll use it to fetch MySQL data and render it in a template. In this case, we’ll set up a route for ‘/’ so that when you visit the root of your application you get a list of your friends from the database. Here’s the entire index.php file:

<?php
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim(); $app->get('/', function () use ($app) {
	require_once 'lib/mysql.php';
	$db = connect_db();
	$result = $db->query( 'SELECT id, name, job FROM friends;' );
	while ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
		$data[] = $row;
	}

	$app->render('friends.php', array(
			'page_title' => "Your Friends",
			'data' => $data
		)
	);
});

$app->run();

After setting up Slim this code creates a route for ‘/’ which you’ve already seen. From there, we include the mysql connection function we created earlier and connect to the database. Next we get a record set ($result) and loop through all records, storing them as $data. Finally, we pass that data (plus any other data we need) to a template using Slim’s render() method.

Template

Templates allow you to show your data off to the world. There are many template languages that you can add to Slim using custom Views, but for now we’ll use a simple PHP file as our template. By default, templates will go in a directory called templates/ in the root of your application.

You can pass data when you render a template. In this example we’ll pass a page title and the MySQL data that we converted to an associative array previously. Here’s what our template file, named friends.php, looks like:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title><?php echo $this->data['page_title']; ?></title>
</head>
<body>
<?php
foreach ($this->data['data'] as $friend) {
	echo $friend['id'].' - '.$friend['name'].' - '.$friend['job'].'</br />';
}
?>
</body>
</html>

That’s it!

Once you’ve got all of these pieces in place, you’ll have a functioning Slim application. Just visit the root of your application and you should see a list of friends from the database!

Download the full test application with commented code

Canonical domain redirects with Apache Virtual Hosts

There are plenty of reasons you might have multiple domains pointing to the same site. In addition, it’s usually wise to configure your site so that it’s available at both domain.com and www.domain.com. But it’s usually a good idea to make sure all of these domain variations point to one proper, canonical domain.

There are a number of ways to set up canonical redirects in Apache. The most popular is probably using .htaccess, but you can also use Virtual Hosts. I prefer that method because it lives outside the web root, so other developers on my team are less likely to tamper with it. Here’s how you do it:

<VirtualHost *:80>
 ServerName www.domain.com
 ServerAlias domain2.com
 ServerAlias www.domain2.com
 RedirectMatch permanent ^/(.*) http://domain.com/$1 
</VirtualHost>

<VirtualHost *:80>
 ServerAdmin webmaster@localhost
 ServerName domain.com

DocumentRoot /var/www/domain.com/public_html
# continue configuring your site here

In this example www.domain.com, www.domain2.com, and domain2.com will all redirect to domain.com, which is the primary or canonical location of your site. After the ServerName line in the first block you can put in as many ServerAlias lines as you want, and they’ll all forward to the domain that you specify in the RedirectMatch line.

Note that if you have www in the domain of a WordPress site and you follow these instructions to remove the www, you will get a redirect loop. Instead, update your WordPress config first, and then update the virtual host config.

Crucial skills for people who work on the web

Sideproject has written up a great list of skills for people who work on the front end of websites. It includes learning a CMS (I favor WordPress, in case you hadn’t noticed,) taking a thoughtful approach to front-end frameworks and CSS preprocessors, learning the details of Responsive Design instead of just how to hide pictures and change the navigation, and more.

We’re all working in a time when the role of a front-end developer is expanding. Being pretty good at HTML and CSS doesn’t cut it anymore. Sideproject’s post is a great guide toward beginning to think about the other skills you should master in order to be a highly versatile and employable designer/developer.

Original post: http://sideproject.io/web-design-skills-and-experience-musts

 

Lower the WordPress SEO meta box priority

WordPress SEO by Yoast is a great plugin, but its meta box gets high priority on your post edit screen and that can be a little annoying–particularly when it shows up in the middle of your other meta boxes. Fortunately, Yoast has put a filter in place so you can adjust the priority.

To lower the priority of the WordPress SEO meta box, you can put the following code in your theme’s functions.php file:

function lower_wpseo_priority( $html ) {
    return 'low';
}
add_filter( 'wpseo_metabox_prio', 'lower_wpseo_priority' );

Pretty simple fix for a common annoyance.

Convert OpenWeatherMap’s Kelvin temperatures with PHP

OpenWeatherMap.org’s API returns temperatures in degrees Kelvin, which is probably the best temperature scale for scientific use but is meaningless to most people in day-to-day life. Here are a couple of functions to convert it to your temperature scale of choice:

Fahrenheit

function k_to_f($temp) {
    if ( !is_numeric($temp) ) { return false; }
    return round((($temp - 273.15) * 1.8) + 32);
}

Celsius/Centigrade

function k_to_c($temp) {
	if ( !is_numeric($temp) ) { return false; }
	return round(($temp - 273.15));
}

If you want to preserve decimal points, you can remove or modify the round() function to get the level of precision you want. Personally, I’ve never found decimal places in temperatures useful day-to-day.

Import multiple WordPress posts with the same name

By default, the WordPress import plugin will not create multiple posts with the same name which were created on the same date. I’m not entirely certain why this is the default, non-configurable behavior but in an era where WordPress is so much more than a blogging engine there is no limit to the number of cases where it isn’t desirable. Maybe you have a post type for business locations that is arranged hierarchically and each location has a child page called “Contact Us.” Maybe a hundred other things.

In such cases, I’ve found moving a site from my production server to the live server is problematic, because the WordPress Importer plugin discards all but the first instance of a post. Fortunately, this behavior is easily changed with a small modification to the WordPress Importer.

When the plugin iterates through all of the items in the import file, it checks to see whether or not it should create a post for the current item. It only takes a minor tweak to make it always create the post.

In your plugins directory, find ./wordpress-importer/wordpress-importer.php and look for the following bit of code, currently on line 557 as of plugin version 0.6.1. In future versions the location might be different or it might be rewritten. I’ll try to keep this article up-to-date:

$post_exists = post_exists( $post['post_title'], '', $post['post_date'] );
if ( $post_exists && get_post_type( $post_exists ) == $post['post_type'] ) {
...
}

Simply modify that as follows, and WordPress will create all posts as defined in the import file:

$post_exists = 0;
if ( $post_exists && get_post_type( $post_exists ) == $post['post_type'] ) {
...
}

By setting $post_exists = 0 you are telling the importer that the post doesn’t exist, which makes it work the way you probably want it to. I hope that this behavior will change (or be configurable) in future versions of the plugin, but for now this simple mod will get you going.

Redirecting from WordPress.com to a self-hosted blog

I am occasionally asked if Simple 301 Redirects will allow you to redirect your old blog on WordPress.com to your new self-hosted blog installed from WordPress.org. It won’t but there’s an easy way to do just that.

Simple 301 Redirects only works if you can install it on the site you’re redirecting from. Since you’re redirecting from a WordPress.com blog you won’t be able to install my plugin there. What you can do instead is utilize a premium upgrade offered by WordPress.com called Site Redirect, accessible from the WordPress.com dashboard.

As of January 2014 it costs $13 a year. What it does is redirect all of the URLs from your WordPress.com blog to the same URL at a domain of your choosing. It is, in essence, a domain-level redirect.

How long should you pay for it?

Determining how long to keep your Domain Redirect in place depends on where your traffic comes from. You should be OK to cancel it after a year or two if most of your traffic comes from search engines. Search engines will see the 301 redirect and update their indexes.

If most of your traffic comes from inbound links on other sites you may want to keep the redirect in place indefinitely so those links continue working forever.

Redirect all 404 pages to your WordPress home page

I’m occasionally asked to redirect every 404 error on a site to the home page. There are a couple of reasons why you might not want to do this (see below) but there are also valid cases where it could be the right move for your site. If you’ve decided it’s the right thing to do, here’s how to accomplish it easily in WordPress:

Edit or create 404.php in your theme directory. Replace all of the content inside with the following lines:

<php
wp_redirect(site_url(), 301);
exit();
?>

And that’s all there is to it!

Why shouldn’t you do that?

There are a couple of reasons that redirecting all 404 errors could be problematic.

First, search engines are said not to pass all of a page’s link equity to the redirected page unless the content is very similar. So redirecting pages that used to rank well to the home page won’t work as a sneaky way to boost your home page.

Probably more importantly, though, is the fact that it will be difficult to monitor which links are 404ing since they’ll all just end up on the home page. The usefulness of Google Webmaster Tools and other methods of monitoring 404 requests is not just in preventing future 404s. The real power is that it helps you identify what your users are looking for and where they’re failing to find it. Fixing all 404s in an automated way makes that more difficult.