This post was written 2 years ago and therefore may not be as accurate as more recent posts.

Wordpress Code Header Snippet

Recently here at 3 Door Digital we had a project that required pretty advanced custom URL structures in WordPress. By default, WordPress is pretty good with permalinks, allowing you to specify a whole range of variables to use. For most websites that use WordPress as their Content Management System, you will probably use one of the default permalink structures. However suppose you are working on a website – say for example a law firm – and you want to list all solicitors associated with the firm, as well as their specialty. Suppose you want each solicitor to have the following URL structure:-

/solicitors/specialty/solicitors-name/

How could you do this? You could create individual pages for each solicitor, and nest each page within each speciality. However this could create a lot of redundant pages, and could take a fair amount of time. Alternatively you could use custom posts and custom fields, as well as a little bit of  URL rewriting using WordPress’s internal functions. You can recreate the example URL structure fairly easily this way, here’s how:

1. Create A Custom Post Type

To begin with, we need to create a custom post type called “Solicitors”. This will add an extra menu entitled “Solicitors” to the sidebar in the administration section of WordPress. These posts, separate from your standard posts and pages, will not appear in any blog, but can have added custom fields added to it – in this case “Speciality”.

In your favourite code editor (I recommend NotePad++ for free, or PHPDesigner8 for a paid editor, though Adobe Dreamweaver if you have it is fine), open your WordPress theme’s functions.php, and copy and paste the following lines:-

function tdd_create_custom_post_type() {
register_post_type( 'solicitors',
array(
'labels' => array(
'name' => __( 'Solicitors' ),
'singular_name' => __( 'Solicitor' )
),
'public' => true,
'has_archive' => true,
'rewrite' => FALSE,
)
);
}

add_action( 'init', 'tdd_create_custom_post_type' );

This will create a custom post type using the register_post_type function that will display whenever an admin page is displayed. So you’re not blindly copy and pasting, here is each line in the code explained:-

  • register_post_type(‘solicitors, … - this registers a post type called solicitors with an array of options specified, the options specified are:-
    • ‘labels’ - the name (in English) of your post type – this is what is displayed on screen. You can also specify a singular name using the variable singular_name
    • ‘public’ - This should be true, as you want people to see your post, right? :)
    • ‘has_archive’ – This specifies if that if all posts in question have an archive page or not. I usually set this to false.
    • ‘rewrite’ – This specifies if URL’s for this post type should be rewritten, and if so how. By default, solicitors posts would have the URL /solicitors/solicitors-name/. As we are specifying the URL rewrite rules, we need it to be false.
  • add_action( ‘init’, ‘create_custom_post_type’ ); - As soon as possible when the blog loads, run the “create_custom_post_type” function.

2. Add a Custom Field to a Custom Post Type

We then need to create a custom field associated with this post type. The easiest way to do this is by adding a box that only appears on the page associated with the custom post type. To do this, copy and paste this into your theme’s functions.php file:-


function tdd_custom_metabox() {
global $post;

//Get All the Data for the Post In Question
$solicitorspeciality = get_post_meta( $post->ID, 'posts_solicitorspeciality', true );

// output invlid url message and add the http:// to the input field (will be added later)
if( $errors ) { echo $errors; } ?>

<!-- Build The Box in Question -->

<label for="solicitorspeciality">The speciality area of this Solicitor

<input id="solicitorspeciality" type="text" name="solicitorspeciality" value="<?php if( $solicitorspeciality ) { echo $solicitorspeciality; } ?>" size="37" /></label>

<!--?php } /** * Process the custom metabox fields */ function tdd_save_custom_metabox( $post_id ) { global $post; if( $_POST ) { update_post_meta( $post--->ID, 'posts_solicitorspeciality', $_POST['solicitorspeciality'] );
}
}

/**
* Add meta box
*/
function tdd_add_custom_metabox() {
add_meta_box( 'custom-metabox', __( 'Specialty of the Solicitor' ), 'tdd_custom_metabox', 'solicitors', 'normal', 'high' );
}

add_action( 'admin_init', 'tdd_add_custom_metabox' );
add_action( 'save_post', 'tdd_save_custom_metabox' );

Here is what each line of the code does:-

  • Lines 2-17 builds a meta box which adds a “speciality” field. If the current post has a “speciality” defined already (i.e. it’s not empty), this is prepopulated when the post loads.
  • Lines 22-28 saves to the database the value of the speciality field for that post whenever the post is saved.
  • Lines 33-35 adds the “speciality” field to a custom meta box on any post that is a “solicitor” (as we only want the box appearing on a “solicitor” post type, not every post or page). The box title is “Speciality of the Solicitor” and the contents of the meta box is the output of the “tdd_custom_metabox” function.
  • Line 37 states that if we are currently on an administration page, we run the tdd_add_custom_metabox function to see if we can add the meta box created in lines 2-17.
  • Line 38 makes sure that lines 22-28 are run whenever a post is saved.

3. Build the Post URL Using The Custom Field

You now need to rewrite the URL adding in the custom field to the URL. To do this we use two WordPress functions – add_rewrite_tag and add_permastruct.

These two functions basically change the URL structure so that we can add more data into the URL, which will then be changed back to a standard permalink. This is all done on the fly, before WordPress even loads the page, so users aren’t aware of it happening.

To begin with, we will create the function that will change the permalink structure. Copy and paste the following into your functions.php file:-


add_action('init', 'tdd_add_rewrite_rules');

function tdd_add_rewrite_rules()

{

// Register custom rewrite rules

global $wp_rewrite;
$wp_rewrite->add_rewrite_tag('%solicitors%', '([^/]+)', 'solicitors=');
$wp_rewrite->add_rewrite_tag('%posts_solicitorspeciality%', '([^/]+)', 'posts_solicitorspeciality=');

$wp_rewrite->add_permastruct('solicitors', '/%posts_solicitorspeciality%/%solicitors%', false);

}

If you try creating a custom post now, you won’t be able to access any post. The reason being that the URL of the blog post will contain the phrase %posts_solicitorspeciality%, which is invalid.

We now need to replace all instances of %posts_solicitorspeciality% with the value of the custom field, when the post is created. To do this, paste the following into your functions.php file.


add_filter('post_type_link', 'tdd_permalinks', 10, 3);

function tdd_permalinks($permalink, $post, $leavename)

{

$no_data = 'no-speciality';

$post_id = $post->ID;

if($post->post_type != 'solicitors' || empty($permalink) || in_array($post->post_status, array('draft', 'pending', 'auto-draft')))

return $permalink;

$var1 = get_post_meta($post_id, 'posts_solicitorspeciality', true);

$var1 = sanitize_title($var1);

if(!$var1) { $var1 = $no_data; }

$permalink = str_replace('%posts_solicitorspeciality%', $var1, $permalink);

return $permalink;

}

This will replace all instances of %posts_solicitorspeciality% with the value of the speciality field. If nothing is there, then the value “no-speciality” will be used in the URL. This is to avoid the URL structure of /solicitors//solicitor-name.

That’s pretty much it! You can do some advanced jiggery pokery to add on more variables to the URL, creating subfolders and subfolders. I talk about this in the download below. You can download a copy of the above code to copy or paste (or include) into functions.php.

To download the code, which is far more annotated, click the link below:-

Click Here To Download

Any queries, please let us know in the comments!

Categories: WordPress

Rhys Wynne

Posted by

Rhys is the Lead Developer at Firecask, and leads many projects both inside and outside of work. He has over 4 years commercial experience in PHP development, specialising on WordPress, and 7 years SEO experience. He is a published author with his first book - bbPress Complete - published in July 2013.

Comments

    Comments are closed.