WordPress Development 101: A starting point for PHP developers who want to use WP

June 5, 2014 | PHP, Teaching, Time Savers, Tutorials, Wordpress | 0 comments

You might want to set aside some time to read this as it’s quite a long post. It’s all I could think of over a few days of writing but if you have any ideas for areas to extend the guide then please post a comment or contact me.

I have had the same conversation with a few people now.. you know the one. “I have been a PHP developer for a fair few years now and really WordPress looks like too much to learn in order to be successful”… or words to that effect. Essentially because it’s something they have never used before people seem to discount using it all together whilst never realising that everyone needs to start somewhere (that said I have been meaning to look into App development for a few years now and find myself giving the same excuses!). This little guide is something I have put together to give people a starting point in the hierarchy of a WordPress site and some of the coding basics to give you an idea of where to start. It may grow over time but for the moment let’s see where writing this takes me 🙂

Where do I start?

Well you can go and get the files! At the time of writing WordPress 3.9.1 is the latest release although this guide will be something that will be mostly useful for a fair few versions to come. The WordPress developers site is http://wordpress.org/ and there is a rather obvious blue link there to allow you to download the files. Getting a development environment set up is as easy as unzipping the files into a web serveable directory and visiting the site. The ‘famous’ 5 minute install stands true to it’s name and will be a doddle as long as you have a MySQL database good to go. The default table prefix is wp_ but this can be changed (but don’t.. just leave it. Unless you’re a security nut!). Once you’ve run the install you can visit your site where it will have added a couple of bits of default content and given you the base level of setting for a WP site. Admin controls can be found on the admin panel at /wp-admin and you can login and play with the site from there. The majority of developer necessary settings are in the tools menu and the settings menu on the left hand side of the admin menu.


Finding your way around the files is going to be a pain in the backside. Some developers like to get down and dirty with the files before using the thing.. once again don’t do this. You will get confused and frankly there isn’t much point unless you’re one of *those* people. For us normal developers the following couple of statements will be useful enough to get you started… Everything to with WordPress is focussed on abstraction from the core. Nothing you will ever do on a WordPress site will require you to touch a core file and as an extension to this you will never need to edit an existing plugin… you either override it or write your own. It’s the WP way! It will get to the point where you spend hours coding around something someone else has done because their approach was laughable… any WP dev (worth their salt) has been there and been in tears when a plugin developer hasn’t bothered to include appropriate actions or filters in their work to allow others to hook in when they need to. It’s painful but you soon learn which plugins are worth using or not.. call it a rite of passage. Essentially there are three main directories in the package: wp-admin, wp-content and wp-includes. NEVER go anywhere near wp-includes or wp-admin with a view to code. It’s a more look don’t touch arrangement in there. wp-content on the other hand is semi-structured. It contains, by default three more directories (although this grows with plugin addition and other circumstances that aren’t relevant right now). These are plugins, themes, uploads. Very briefly before moving into more detail these are as follows:

  • Themes – where your themes are kept
  • Plugins – where your plugins are kept
  • Uploads – you guessed it.. where the bodies uploads are kept

Uploads is a little bit of a question mark because firstly it doesn’t exist until you visit the site and secondly it can be moved in the media settings admin page (again something *those* people like to do.. frankly not worth doing). So if you are looking to change something to do with the layout of the site you need to look at the wp-content/themes directory or if you need to edit or add a plugin its in wp-content/plugins.. simples! Never touch anything else except for the exception of the wp-config.php file which lives in the root if you want to add one of many obscure and largely unnecessary constants. Finally the .htaccess file is generated ONLY when you select an option other than default in the permalinks (URL structure) page in the admin console (/wp-admin in your browser then settings->permalinks).


A plugin is a plugin… what does it sound like? Essentially a bit of code that hooks into the site and does *something*. Excellent summary right? Ok I’ll try harder… a plugin is a set of functions or classes which, when activated (admin console > plugins > pick one > activate) will be called at the beginning of the page load and is invited to ‘hook’ into the core at a variety of points (see actions and filters) to do any number of things. This might be adding huge amounts of functionality (ecommerce, forum, social media for example) or something small (a widget, removing a banner nag, changing the login logo). Essentially a plugin is your go-to place for doing anything with a WP site from a code perspective. The only other place to do anything is within the theme files and there are huge debates online about what goes where as a matter of best practice. As a rule of thumb if the functionality you want to add is standalone like adding ecommerce or a new widget for example then it’s a plugin whereas if you want to do something to compliment the layout of your site or change something to do with the look and feel then changing the theme is your best bet. Most people will favour the theme because it’s more work to write a plugin from scratch than it is to bash a few lines of code into the theme which already exists.. more from that in the themes section below.

Writing a plugin

WordPress is rather clever in that it knows that a plugin is by name, author, url, version and tag. The way it does this is firstly to scan the wp-content/plugins directory and look within PHP files. It then looks at the top of those files for a PHP comment and parses it for a number of keywords which define what that plugin is called and how it should be presented in the system to the user/admin. It’s rather easy to make a plugin.. simply create a new text file, copy in a stub PHP comment from an existing plugin (any will do), change it, save as a PHP file and upload. It doesn’t matter if it’s in a directory or not although it’s best practice to use on in case you want to add companion files to the package. Here is an example of the hello dolly plugin which was one of the first written for WordPress and is included in every release. It’s both an excellent nod to WordPress history but also an excellent template to use for your own plugin. You can see the file here. The important part is the top comment as follows:

Plugin Name: Hello Dolly
Plugin URI: http://wordpress.org/extend/plugins/hello-dolly/
Description: This is not just a plugin, it symbolizes the hope and enthusiasm of an entire generation summed up in two words sung most famously by Louis Armstrong: Hello, Dolly. When activated you will randomly see a lyric from <cite>Hello, Dolly</cite> in the upper right of your admin screen on every page.
Author: Matt Mullenweg
Version: 1.6
Author URI: http://ma.tt/

It won’t take a genius to change those values and save out as a new file. Simply adding your file to the plugins directory will be enough to have the system recognise it. But it will never be called until the plugin is activated in the admin console on the plugins page. Once it is activated though if it has an error or hole then it will effect the site so make sure to avoid fatal or syntax errors before activating. Once active the plugin an be modified using FTP or via the inbuilt file editor (former heavily recommended!).


Many people get confused when they hear theme. Essentially a theme is a skin or ‘look and feel’ for a site. WordPress ships with a few default themes which you can both see and customise on the themes admin page. Much like plugins, themes live in a specific directory on the server and not a single file will be called until that theme is active. Unlike plugins only a single theme can be active at any one time. This can be done by clicking appearance in the admin interface. Themes come in all shapes and sizes… a developer such as much self might prefer something more simplistic/minimalistic with no more than a base style and the necessary files whilst other developers who perhaps are not as confident or maybe prefer to edit rather than create can source a theme with admin panels, drag/drop layout builders and many more things. In fact a lot of themes (often premium themes bought for peanuts on marketplaces such as theme forest) contain plugins of their own and have their own mini ecosystem which sits on top of WordPress. It’s hugely popular these days for a theme to come bundled with a few sliders, be fully compatible with a number of eCommerce packages and have handy tools like drag/drop page builders and customisation panels allowing you to do everything from changing widths and sizes to changing colours and fonts. My preference is the former… I hate working on sites where it claims to do ‘everything’ because invariably when you find something it doesn’t do it’s a right pig of a job to change it. But it’s largely a preference thing and, as a new WP developer, you will find your own preference.

Custom theme development

As stated above you can buy a theme, use a free one or you can write one yourself. Dependent on the site or job you might do all three. a common job for a WordPress developer is PSD to WP conversion whereby a graphic designer client will pay you to make a WordPress theme from a design they have made. The process isn’t actually too hard once you know the hierarchy of a WordPress theme and how to go about it. The rest of this guide will focus more on the technology and structure of the framework to help you develop themes and plugins to suit whatever the need of the day might be. A WordPress theme contains any number of files from two or three to hundreds depending on the size and complexity (see my above comment about premium themes with excess functionality). The most common *normal* themes have maybe 10 files that matter and some includes for CSS, JS and images. The structure of these files is incredibly similar as each file is only called under a certain circumstance. In simple terms the following can be used:

  • header.php – called by most other theme files using the helper function get_header(); It contains what you would expect, that being everything from the header tag down tot he body tag and some of the opening page markup. Crucially must contain reference to wp_head(); in the head section as WP uses this to add it’s own code into your structure.
  • footer.php – as above just the closing markup called using get_footer(); from the template file. Must call wp_footer(); for any footer info required by WP.
  • functions.php – a function dump for any and all code. Called every page load so you can add your own custom functionality in here if you like but ideally should be used to include other files for the theme and to add any hooks (actions or filters) you might need to interact with the WP core. Minimally this file can be empty if you like.
  • index.php – required by the theme. Default fallback for everything else but at the very least it forms the layout for the ‘post’ post type (standard place for blog posts/news items. post is a built in post type)
  • page.php – layout for ‘page’ post type items (static content such as about us, contact us etc.. page is a built in post type)
  • single.php – layout for single items of ‘post’ post type. Much the same as page but the different between index and single is that index is for several items in an archive format (10 items per page with pagination at the bottom) whilst single references a single item (single news item or blog post).
  • archive.php – the same as index.php but is used for archives (funny that!). An archive is something like all posts in a category or all posts by an author. Essentially collections of content which have been filtered whereas index is just the blog homepage showing all content in an archive layout
  • style.css – crucially the most important file containing the CSS comment which defines the files in the directory as a theme. Much like the plugin example above a theme is defined only by the comment in the style.css file in the similar fixed structure as you might find in a plugin. More on this later
  • screenshot.png – used only in the admin console to graphically present the theme. Not necessarily required but gives the theme a bit of professionalism. The file should be a PNG and the ideal dimension used to be 300×225 but I believe WP now supports JPG and large image sizes.. like I said it’s not necessary but a nice touch

As you might have guessed, WordPress operates on a fallback system in the theme files. Essentially if a specific granular file doesn’t exist then it will try a different file name eventually ending up at index.php. This might sound cumbersome but it’s incredibly powerful allowing you to override almost any type of file or data type at the template level simply through the file name. This handy guide shows exactly that as a graphic to hit the point home. When I was learning theme development a few years ago this was open pretty much permanently! The following CSS comment is taken directly from the twentyfourteen theme (default with all WordPress installations out of the box currently). It denotes the comment that needs to be added to the style.css file for the files you have put into that directory to be treated as a theme:

Theme Name: Twenty Fourteen
Theme URI: http://wordpress.org/themes/twentyfourteen
Author: the WordPress team
Author URI: http://wordpress.org/
Description: In 2014, our default theme lets you create a responsive magazine website with a sleek, modern design. Feature your favorite homepage content in either a grid or a slider. Use the three widget areas to customize your website, and change your content's layout with a full-width page template and a contributor page to show off your authors. Creating a magazine website with WordPress has never been easier.
Version: 1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: black, green, white, light, dark, two-columns, three-columns, left-sidebar, right-sidebar, fixed-layout, responsive-layout, custom-background, custom-header, custom-menu, editor-style, featured-images, flexible-header, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready, accessibility-ready
Text Domain: twentyfourteen

It’s a little bit more complicated than you might find in a plugin but most of the lines here are not required. The more you use the more exciting the theme selector page will look but frankly most of it is not necessary. Below you will see the amount of detail I would add using the above example:

Theme Name: Twenty Fourteen
Author: the WordPress team
Author URI: http://wordpress.org/
Description: Theme from design for X (client name)
Version: 1.0

Yup that’s it.. who needs to know more than who wrote it and what it’s for I won’t lose any sleep if people don’t know what license it has or what tags it has. Text domain is important if you want to localise (translate) your theme but if you are just starting out it’s not really necessary. When developing a theme from scratch I like to use a free developers theme called Bones. It isn’t designed to have a child theme (described below) but instead it’s designed to be butchered. The author makes regular updates via GITHub and has fully documented both the code and CSS. A great starting place if you don’t yet know your way around a theme. Get it here: http://themble.com/bones/

Child themes

In the last couple of years as the WordPress upgrade system got better the ability to upgrade a theme was introduced and theme developers started changing their themes, adding frameworks, fixing bugs and using the system to release these changes to the world. Until then the way to work with a theme (whether you bought it or not) was to edit the files directly. This was dropped on it’s head when updates came along and themes you have written for people based on an existing theme was promptly overwritten when overeager clients pressed the big orange upgrade banners they suddenly saw on their sites. To combat this annoyance, something called a child theme was introduced meaning a theme could be created as almost a slave to another. So you could safely upgrade the parent theme and not lose your custom changes. How they work is simple.. Under normal circumstances, when a page is loaded (a blog post for instance using single.php) the framework will look for single.php in the theme directory. In a child theme setup the framework will first look in the child theme for single.php and if it doesn’t exist it will fall back to the same file in the parent theme. Essentially if you want to add your own header.php but leave the rest as standard then you add a child theme with only header.php inside. It’s not quite that simple but it works nonetheless. Setting up a child theme uses another line added to the theme declaration comment in the style.css file. Basically you just name the parent theme on a new line. So you create a new directory in wp-content/themes and add a new style.css file with the normal CSS comment and one more line. Once you’ve done that you can go and activate it as you would a normal theme and WordPress does the rest. Obviously the parent theme needs to be in the themes directory on the server but you don’t need to make any code changes to it. This handy guide to setting up a child theme will get you started. I prefer to use Bones myself and make my own themes but this is really useful when using a commercial theme with a complicated drag/drop page builder or an admin interface as there will inevitably come a time when an upgrade is released and your client overwrites all of your hard work!

The WordPress Database

Whilst steaming hulks of mess such as Drupal and Joomla have huge cryptic databases which are a maze to navigate WordPress has somewhere in the region of 10 tables. As previously mentioned the database prefix can be changed but it defaults to wp_. You might want to bear this in mind when writing your queries (more on that later). The prefix, if you don’t know what it is, can be found in the /wp-config.php file in a constant. For the purposes of this tutorial though we shall assume the default wp_ is used. The main site content is all stored in a single table along with a raft of other stuff which I shall detail when talking about custom post types in the next section. That single table is wp_posts. The important column is ‘post_type’ to check what sort of data you are looking at and of course ‘post_status’ to check if a piece of content is ‘published’ or not. The database works loosely by storing an item and then attributing data to it in ‘meta’ tables which work on a key-value pair basis which makes it really easy to use and to query. There are a few key data types, those being posts, users, comments, taxonomies and any associated data which follows a standard model. It’s not normally common practice for a plugin to add custom tables so getting used to working with the WP tables is generally a good idea. That isn’t to suggest you can’t add your own tables but it’s generally only done for larger plugins such as eCommerce and Forum offerings. The only other major table worth mentioning is wp_options which stores site settings in a similar key-value format. On the WordPress admin settings page you can safely assume that ever setting stores it’s data in the wp_options table. There are handy helper functions to pull data from these tables which I shall mention shortly. I won’t list the tables as WordPress have nicely documented it for you here: http://codex.wordpress.org/Database_Description

Querying the Database

The three key objects within WordPress are post, user and option (option being settings stored in wp_options). They follow a similar key-value pair format and can be pulled by named index very easily from anywhere in your plugin or theme files. post stores it’s associated data (meta) in wp_postmeta and user meta is stored in wp_usermeta. The helper functions for these two are used as follows: Adding meta to a post or user:

update_user_meta($user_id, 'named_meta_key', 'Value to store.');
update_post_meta($post_id, 'named_meta_key', 'Value to store.');
update_option('named_option', 'Value to store');

The named (meta key) of what you store is entirely up to you. It’s best practice to prefix your custom data to save interfering with core or other third party meta data but for all intents and purposes it can be treated as free text. I would recommend using hyphens or underscores between words in the meta key and keeping it lower case (for no other reason than to avoid me going into an OCD fuelled rage when I end up fixing your work for my clients down the line). These ‘update_’ functions have ‘add_’ counterparts but frankly ‘update’ does the same job with the added bonus of updating the existing value if a meta key by the same name for the same object already exists. I always assume a one to one relationship whereby you can have a single value stored for a specific name against a specific object. In fact that’s not true, you can have multiples which generates an array when pulled but in the last 5 years I have not used nor come across a plugin that uses multiples by the same name. The slight difference in naming is apparent when working with options (sitewide settings) as a meta key becomes an option name and a meta value becomes an option value. Don’t be alarmed though as they are the same thing. The main different between options and meta items is that meta requires an object to link the data to. eg: user meta requires a user whereas options are sitewide so need no unique ID to link to. At this stage I should mention that you can store any data type in meta or an option without the need to pre-validate. Also to make this more explicitly clear you can store arrays or objects without the need to do anything with them. WordPress will serialize them for storage and unserialize on the way out when queried (only when using a WP helper as detailed below. For obvious reasons if you write your own query you will get the raw data). Pulling the stored data is as easy:

$value = get_user_meta($user_id, 'named_meta_key', true);
$value = get_post_meta($post_id, 'named_meta_key', true);
$value = get_option('named_option');

It’s as simple as that.. $value will be populated with the content of the meta value or the option value depending on the object you query. The third argument for the two meta queries is always ‘true’ when you want a standard variable back and not an array. When I said that a meta is a one to one relationship this is just a way of ensuring that what you are pulling is never an array of meta values. Options don’t need this argument adding because it’s an explicit one to one relationship although it’s very common that what’s stored will be an array or object. Optionally with get_option a second argument can be define which is the default return value if no option exists. This is particularly useful for settings objects or arrays whereby you expect an array to come back but in fact it’s boolean false. You would then need to test the return value before using it. If you define an empty array or object as the return then you get the data type you were expecting. I rarely use this second argument myself but it’s handy to know it exists. There are ‘delete_’ counterparts for these data types above but I won’t go into that for now.

Writing SQL

Most of the time you never need to write an SQL query but if you do you can use the $wpdb global class object to work with which completely removes the necessity to use the more traditional ‘mysql_’ functions provided by PHP. There is a rather comprehensive class description here but as an overview in simple terms the following can be used: When using the global variable $wpdb you mustn’t forget to ‘global’ it into your function or method using ‘global $wpdb;’. You knew that of course but it had to be said! Each of the following examples assumes you have a variable $sql set up which includes the query itself. To get a single value response without the need to pull from an array:

$value = $wpdb->get_var($sql);

To get an array of results:

if ($results = $wpdb->get_results($sql)) {
    foreach ($results as $row) {
        echo $row->column_name;

To get a single row directly from a query:

if ($row = $wpdb->get_results($sql)) {
    echo $row->column_name;

To insert into a table:

$new_id = $wpdb->insert_id;

Custom Post Types

Stepping away from the world of code for a moment and back into terminology and site object structure we move swiftly into post types. You might be aware that WordPress ships with a couple of data types built in.. those being posts and pages:

  • posts – chronological content such as a news feed or a blog post whereby there is no concept of hierarchy and posts are sequential. Posts are a non-hierarchical post type.
  • pages – Contrary to posts, pages are hierarchical and can be placed into a tree structure (pages which have parent/grandparent pages) which directly effects the URL. For instance the following URL is common: http://www.yoursite.com/parent-page/child-page

Pages are by far the most common type of data on a WordPress site. In fact 90% of the sites I develop for have just the page post type in use. My clients often are too lazy or don’t have the right amount/frequency of content to write sequential/chronological content such as a blog or a news feed. These sorts of sites I refer to as ‘brochureware’.

Now the fun bit… whilst post types have always been a part of WordPress, a few versions ago it was made more public that you can make your own. It really opened up the framework and gave it credibility as a CMS and not as a blogging platform as it was understood to be before then. So from then on plugin developers and theme authors started to use custom post types to add new and exciting types of content to their work but minimal effort.

By way of example if you were creating a site where you wanted both a news feed and a blog you could use the ‘post’ post type and create a new non-hierarchical post type for the news feed. Or if you wanted to create a gallery or portfolio you could have a new hierarchical post type called gallery or similar.

The thing you will really appreciate about custom post types is that when you add one it created the entire admin interface for you. WordPress has fantastic continuity of layout and design in the admin interface and post types are no exception. When you add the code snippet from the example URL I shall give you in a moment it will make a new link in the admin menu which you can click and immediately, with no further code, create, edit, delete items.

Each admin interface for a custom post type can be slightly different to store the information relevant to that type of item. When editing a post type item (a page perhaps) you will notice in the right sidebar there is a page attributes box (a metabox we call these). This only shows for pages. Conversely you will find that the ‘excerpt’ meta box only shows for ‘posts’ by default. Adding a post type for something like a product for a shop means you might want to add the price and some other information. This is there adding a custom meta box comes in. You can simply add a new one using code you will find on this page. I did this defiantly for around 5 years but I’ve decided life is too short to make my own meta boxes when there is a plugin to do that for me. I now use Advanced Custom Fields (a free plugin with some premium addons if you need them) to make my custom admin interfaces. It’s still nice to know how to do it ‘properly’ though if you ever need to make something a little more bespoke as I have done from time to time so keep the link handy for the future.


The templating system detailed in a previous section in this guide will give you a helpful graphic showing you which template/theme file will be called but essentially for easy reference the following applies:

If your post type is called books then you can duplicate archive.php in the theme and call the file archive-books.php and it will use that when viewing a list of ‘book’ items. In the same example you can duplicate single.php and call it single-books.php and it will use that when viewing a single book item. This allows for bespoke layouts to be created which apply ONLY to items of that post type. It’s important to remember though that you don’t need to do any of this template editing because if the ‘-books.php’ suffixed files are no present the wonderful fallback system within WordPress will simply use archive.php or single.php (consult the graphic in the template hierarchy link above for more info on this).

For more information on custom post types just visit the following link. Scroll to the bottom for a copy/paste code example.

You can pull content from the wp_posts table in a number of ways but the main and accepted approach is to use the WP Query object. It does take a bit of getting used to but essentially you build a structured array and pass it to a class constructor which then allows you to loop through the results. It’s a little awkward to explain but I have written a code snippet here which returns an array you can simply use foreach to iterate over. Normally when working with custom post types for adding something like a news feed then writing your own loop won’t be necessary as you would use the theme files (archive-news.php for instance) and it would simply work out of the box. However, consider using a post type for something like a slider.. if you were to create a jQuery slider where the slides are editable via WordPress then the logical choice is to use a custom post type. In that circumstance you would want to query the post type items and include in a structured bit of markup before adding the appropriate jQuery to make it function. Using my code snippet or a function like get_posts is where you would start there. I actually wrote a slider plugin for WordPress back in 2012 using a custom post type so looking over the free plugin as an example might be a good idea. It’s only a small plugin so should be easy to digest and see the approach. Get it here.

Taxonomies (including custom taxonomies)

A taxonomy is the WordPress way of labelling a tag or more accurately a way of naming something which you can apply to a post type item. More commonly thought of as tags and categories which exist by default for the ‘post’ post type. Collectively referred to as taxonomies. You can theme round taxonomies using the template system so a category archive can look different to a tag archive or even a specific category term (a term is a specific tag or category.. a single taxonomy item if you prefer) for instance.

You can very easily add your own taxonomies to things. Consider the following example:

You are building a property directory for an estate agent.. you want to log against each property the county/city and the sale and/or rental status. County could be a taxonomy whereby you pre-populate a list and the data entry person just selects the correct one, city could be another taxonomy (or included in the first as child items of each county) and finally the sale/rental thing could easily be a couple of checkboxes with one or both available to check. Using a taxonomy means, much like a category that an archive page is automatically made accessible for the term. For instance if I were to categorise this post in ‘tutorials’ then you would see it appearing on this page: /category/tutorials. Note the URL /category is the base for the taxonomy and the tutorials part is the term itself. In the above example the sale/rental status might be a taxonomy called ‘tender’ meaning the equivalent archive URL would be http://www.yoursite.com/tender/for-sale and clicking that link would show all properties which fall into that category. In addition to the archive pages using a taxonomy also opens up a whole raft of search and filter functionality which can be added later on… if I were building a property directory I would expect to write an advanced search to filter by one or many of these taxonomy terms and post types.. In actual fact I have written property searches for a couple of my clients in the past so this is a real life example.

As stated tag (post_tag is the name in the system) and category taxonomies are added to the ‘post’ post type out of the box but adding your own taxonomies, much like adding a custom post type, can be really easy. use the code example at the bottom of this page to add your own.

Note that when adding custom post types and custom taxonomies you might need to re-save your permalinks (url structure settings) to get it to take properly. This is as simple as logging into the admin console and visiting settings then permalinks. Visiting the page I believe is enough to do it but I tend to press save on that page anyway for good measure! Either way it does the job so if you get a 404 when visiting a custom post type or custom taxonomy term or archive page just re-save your permalinks!

Hooks – Actions/Filters

A bit more code now for you to enjoy… WordPress is an abstracted model as I have stated above. This means (to me at least) that all custom functionality is entirely abstracted from the core files. The next obvious question is going to be how do we then ‘hook’ into the core functionality from within a plugin or theme. This is where hooks come in.

There are two types of hook within WordPress.. ‘actions’ and ‘filters’. Both are mostly the same except filters expect you to return something and actions are just send and forget type function calls. For example.. you want to sign a user up to mailchimp when they register. By definition this requires no return value.. we simply want to be able to hook into the site at the registration event and fire an API call to mailchimp to do the rest. The code would look like this:

add_action('user_register', 'my_user_register'); //note the third and fourth arguments are priority (default 10) and argument count (default 1)
function my_user_register($user_id) {
    //execute mailchimp API call with data from $_POST

On the other hand a filter is a ‘passthrough’ function.. it will be passed a value and it will be expected to return something in the same format (if it receives a string it should return a string to save breaking the site). A great example of this is a login redirect. When you login to a WordPress site you are taken to a very grey coloured and very WordPress looking profile page. Most people don’t want this as firstly the continuity of theme is lost and secondly it’s common practice for a plugin to be used to have a prettier profile page elsewhere and on a better URL. For whatever the reason the point is you would want to be able to cause a redirect on login. So WordPress defines the profile page as a default URL and then makes it available to filter on a named breakpoint. Plugins or the theme can then hook into this named breakpoint (with an optional numeric priority figure to help things along) to augment the URL. The function you declare within the filter will receive the profile URL and you may do some processing and return a completely different URL if you like.. or just return the same thing. See the following example to highlight this:

add_filter('login_redirect', 'my_login_redirect'); //note the third and fourth arguments are priority (default 10) and argument count (default 1)
function my_login_redirect($original_url) {
    return 'http://www.google.co.uk'; //send the user to Google for no apparent reason

The two essential pages to keep bookmarked for working with hooks are the action reference and the filter reference. They detail the hooks called throughout the typical page load and atypical pages such as login and register. Note that you can define your own actions and filters to use yourself for your files to talk to each other or for other developers to hook into your code. This is immensely useful when done.. in fact even if you spam hooks all over your work then it means that any other developer can creatively extend and increase the value of your work with little or no effort on your part. You can simply add the hooks or add the hooks and document them.. but then who reads documentation anyway 🙂

As a quick guide the following two lines of code can be used to add your own hooks.

do_action('my_test_hook', $variable1, $variable2); //set an action breakpoint passing any function or method hooking into it two variables
$variable_value = apply_filters('my_filter_hook', $variable_value, $helper_variable1, $helper_variable2); //set a variable but allow it to be filtered and pass two supplementary arguments to help with processing

If you add a few of these to your code then other developers will be rather happy. An excellent example of this is the most popular eCommerce plugin for WordPress called WooCommerce. WooCommerce has hundreds of hooks throughout it’s codebase (a simple ‘find in files’ from your IDE is a great start when looking for them!) and because of this there is now a huge community of developers writing companion plugins to make WooCommerce better. For instance if you want to add additional shipping modules or payment gateways then you can write a plugin and user a specific hook in your code which is picked up by WooCommerce and utilised. It’s very good indeed. You are seeing hook usage more and more in third party plugins so don’t be shy of using them!


Shortcodes are used within the TinyMCE editor within WordPress to hook in code of your own to be called at runtime. They are immensely useful and very commonly used so it’s worth knowing how to recognise them and of course write your own. Essentially if you edit a piece of content and see something written in square brackets then it’s a shortcode. Commonly they are used either to hook in larger systems onto a page or to add custom markup around content using encapsulating shortcodes. Examples are:

"Hello my name is [flash]Sean[/flash]"

In the above example if there was a shortcode called flash then it would call a function which would most likely add an HTML blink tag around the content that you ‘pass’ to it. This example is an encapsulating shortcode whereby the content within the shortcode tags (opening and closing denoted by a preceding forward slash.. much like HTML but using different brackets) is passed to the hooked in function and returned. if it isn’t returned then it’s removed. The following code example would power the above shortcode:

add_shortcode('flash', 'my_flashing_function');
function my_flashing_function($attributes, $content) {
    return '<blink>' . $content . '</blink>';

That would cause the blink. However the handy thing about encapsulating shortcodes is that you don’t actually have to return what’s passed. It’s how I got into WordPress myself actually.. via a membership plugin which allowed you to restrict access to content on your site by a paid for or assigned role. In that example the following somewhat more complicated example applied:

add_shortcode('flash', 'my_flashing_function');
function my_flashing_function($attributes, $content) {
    if (role_checking_function()) {
        return '<blink>' . $content . '</blink>';
    } else {
        return 'Sorry you have no access to this content';

So it would check the role and if they didn’t have access then the resultant string would be:

"Hello my name is Sorry you have no access to this content"

Not pretty I know but you would generally encapsulate paragraphs using my access checking shortcode rather than words.

The other major use of shortcodes is the non-encapsulating sort which are used to include third party code onto pages. For example if you had an eCommerce package and wanted to include a buy now button on a page you might use a shortcode such as [add_buy_now product_id=123] or if you wanted to include a gallery of images (via a gallery plugin) then you might use something like [include_gallery id=123]. I’m clearly making these shortcodes up as if I stumbled across one which existed already on this site then it would be parsed and instead of giving you an example you would see the gallery or buy now button itself.

The above non-encapsulated examples included an argument with them… product_id= and id=. These are processed out of the shortcode into an associative array and included as the first argument passed to the handler function or method. You can add whatever arguments you want to a shortcode and you don’t need to declare them.. they are just parsed and included. Some shortcodes are several lines long. They aren’t pretty but they are functional and by far the most effective method of including third party dynamic content or manipulative functionality on your site. The following example applies:

"[include_gallery id=123 slideshow="yes" autoplay="yes" images=24 pages=3]"
add_shortcode('include_gallery', 'my_gallery_function');
function my_gallery_function($attributes) {
    return get_the_gallery($attributes['gallery_id'], $attributes['slideshow'], $attributes['autoplay'], $attributes['pages']);

Note: always return from a shortcode handler and never echo. If you echo then the content will be at the top of the content regardless of where you add the shortcode itself

Sidebars & Widgets

A sidebar might sound like a bar that goes at the side.. typically it is. Most themes have a sidebar or two included in a layout which might be 33% of the layout will be a sidebar and the 66% will be the content itself. Some pages have a left sidebar, some have a right and some have one either side. In my opinion the name is misleading as it typically was designed to be a bar for the side but now it has evolved into a container for widgets. Basically you can write these little repeatable boxes that can sit in any number of places on a site (depending on where the theme declares they can go).. they are called widgets. Look at the right hand side of this site (assuming I haven’t changed it at the time of reading!) and you will see a picture of me, a list of recent posts, the ages of my children and some other information. They boxes themselves are called widgets but they sit within a sidebar. I believe there to be three sidebars on the right hand side.. a top one and two adjacent narrow ones towards the bottom of my site. what you might not realise though is that on sites where there are boxes in the footer (typically three or four boxes positioned next to each other at the bottom of a site), these are usually sidebars too. So whilst not at the side the author has used a sidebar to make the footer of their theme very configurable.

Sidebars and widgets can be managed from an admin perspective using a nice drag and drop interface under appearance and widgets when logged in as an administrator. You will see a list of available widgets on the left and a number of container boxes on the right denoting the sidebars. You can simply click and drag a widget into a sidebar and let go. It’s as simple as that adding to an existing sidebar hence the reason they are so commonly used.

You can define your own sidebar to be used in a simple one line function call passing an array of config/markup items. See the info on it here. Once you have defined your sidebar you need to slot it into your theme. This can be done using the dynamic_sidebar(‘sidebar_id’); function call. In your theme you will see reference to get_sidebar();. This is just a wrapper for a include for sidebar.php in your theme which contains a div or two and a call to dynamic_sidebar. There is nothing to stop you making direct calls to it but it’s always a good idea to encapsulate the call with a classed div to make styling the widgets easier down the line. On adding the code you will see a new sidebar box appear on the widgets admin page and you can start using it accordingly. Widgets will be constructed using a containing bit of markup that you have passed to the register_sidebar(); function so you can really define how your widgets are structured on a per sidebar basis.

You can declare your own widgets or use plugins to add their own. Typically bigger plugins will have widgets of their own. eCommerce plugins for instance will have a cart widget and probably a product category list and likely a featured products or something else. There really is no limit to the number of widgets you can define with a plugin or the number you use on your site. Adding your own via code is a case of declaring a class and filling in some fields. There are normally three or four methods in the class, these being admin, update and output. Most people copy the code example and modify to suit so I would encourage you to do this and see where you get to. Simply defining the class per the example code is enough for it to show up on the widgets admin page and can be used immediately. Adding a widget can be found here. As usual copying the full code example from the bottom is enough to get you started. Make sure to change the name of the thing though as it might conflict with other developer’s efforts. Not everyone works to the same levels and standards to deviating from the default function names and formats is a good idea.


WordPress supports a rather nice drag/drop menu builder which is most commonly used for one of three places in your theme. These are:

  • Top navigation – the main navigation for the site
  • Footer links – normally for privacy, cookies and terms pages in the footer. I use menus here because I can then add links to a sitemap or somewhere else without having to write more code
  • Miscellaneous lists of links in widgets

As sites get bigger and especially now mobile compatibility is key I find myself using menus a lot more. Essentially a menu is an unordered list which is driven by an inbuilt admin system and one line of code to include the menu itself. Other than that it’s a styling job. The admin interface itself is tuned just to allow links so there is no risk of confusion unlike widgets where you can add any type of content or interface you like. Basically anywhere you see a list of links with bullets or in a menu on a site I will have used a menu. I really hate to hard code things so using menus is an obvious choice. WordPress comes with a ‘custom menu’ widget built in so you simply add the widget and choose your menu from the dropdown and you’re done.

For theme development you need to declare menu ‘locations’. Think of them as placeholders you can slot a menu object into. For instance you might declare a top and bottom menu location in your theme. These would have a div around them and be pre-styled so as soon as a menu is selected in the admin it will immediately look the part. Using a location method means that you can very easily have unlimited menus set up in the admin system and only use the ones you want in the locations you want. I might have header 1, header 2 and header 3 but I can only assign a single menu to a location so if using 1 then 2 and 3 are not output unless used in a widget or in another theme location.

Defining menu locations is very easy (try this link). If you add the following to your theme functions.php file then it will declare the area existence:

register_nav_menu('header', 'Header Menu');

You then need to call the menu in the markup (header.php or footer.php normally) using the location as an index as follows:

wp_nav_menu(array('theme_location' => 'header'));

We use theme_location in the array to tell it where we want to pull from. This guide will help you understand menus more.

Frankly menus are very straightforward because if you use a theme like Bones then it includes all of the declarations and all you need to do it style it or duplicate existing code to get it to work.


So over 8000 words later I find myself thinking that it’s perhaps a little bit more in depth than I had first assumed. however, most of what I am telling you here is read once and remember. When dealing with terminology and when it comes to coding as long as you know what to Google for then the WordPress codex contains thousands of pages with argument references, descriptions and of course code examples for how to do things. There are also a wealth of websites online which you can trawl for more information about the different aspects of developing for WordPress. This really only scratches the surface but knowing what systems are included for developer use with some basic hints and tips as I have done here for you should be enough to get you part the first hurdle and ,at the very least, talking the talk so you don’t get ripped off when you outsource to developers who make out that jobs are much harder than they really were!

I like to write free plugins and release them via this site. If you look at my plugins category you will see 60+ simple yet useful plugins that you might want to use or deconstruct when learning how to work with WordPress. Once you understand how hooks work and can appreciate the uses for custom post types and taxonomies then you can easily develop plugins of your own.

Any questions or comments on this guide or anything else please use the comment form below, the contact request page on my site or for bigger tasks the hire me form so I can take work off your hands as and when the necessity arises. I am evangelic about WordPress so I encourage you to get involved, contribute to the community and help other people out wherever you can!

Good luck and happy coding!


A Donate Button!


Submit a Comment

Your email address will not be published.

CommentLuv badge

About this site and Sean Barton

Picture of Sean
Sean Barton is a Freelance Website Developer in Crewe, Cheshire. He is a Full Stack Developer but with extensive experience in Wordpress and other Frameworks. He is the Co-Founder of SitePresser, Layouts Cloud and Page Builder Cloud among other things..
This site was set up in 2008 as a tutorial and scripting resource for the PHP language and Wordpress.
Find out more about Sean on the About Me page or use the Hire Me page to get in touch. For more information about Sean's work take a look at the Portfolio

SitePresser is the plugin that packages child themes and layout packs for sale. Works with Divi and Elementor.