I began learning about WordPress by building themes and reading through the multitude of awesome tutorials posted across the net. A lot was learned through trial and error, and a lot was learned from copying and pasting. However, there is one topic for which I have yet to find comprehensive information: the WordPress initialization process. I mean from start to finish, how does the WordPress core take the initial page request and give back such beautiful web pages? It’s time to take the plunge and actually step through the WordPress core, file by file, so I can get a better understanding of how our favorite personal publishing platform initializes itself and then displays my content, all of our content, for the world to see. I hope this post will serve not only as a place that I can return to as a reference but also as a place for all of you to turn to when you need a refresher on the inner workings of the WordPress core structure, or if you’re just starting out and need a better understanding of what WordPress is doing with your theme and your code. Let’s get started…
This post is based on the WordPress trunk code base. All of the links to Core Trac source code point to the trunk version of that code. I’ve done this because the WordPress core will change faster than I can keep this post updated, so following the links will always take you to the latest version of the relevant source, regardless of whether or not the content of this article has been updated. The downside to this decision is that you may follow a link that does not accurately reflect the code base for your version of WordPress. If you need to reference the core code base of a previous version of WordPress, the information in this post will at the very least get you close.
Update: On January 29, 2013 I reviewed the links and content in this post and updated it to reflect changes to the current version of WordPress; which at the time of the update was v3.5.1.
All of the magic flowing out of your server starts with a single file:
index.php. This simple file handles the initial request each and every time a page is loaded from your site. It serves two main functions. First it defines a constant named
'WP_USE_THEMES' and sets it’s value to true. This tells the WordPress core that your site should use the active theme to display the pages it’s serving. Next it requires a file named
wp-blog-header.php. This file sits in the root directory of your site with
wp-blog-header is singularly responsible for three fundamental processes during the initialization of WordPress. First it requires a file named
wp-load.php, then it executes the function
wp() and finally it requires a file named
wp-load.php is also located in the root directory with
wp() function is defined in
template-loader.php also resides in the
/wp-includes directory with
functions.php. We will get to the
wp-includes directory in a little bit. We first have to step through the responsibilities of
wp-load and the files that it requires.
wp-load has a simple yet extremely important role in WordPress’ initialization. It starts by setting a constant named
'ABSPATH' to the root directory of your WordPress install. This constant is used extensively throughout the remainder of the initialization process to easily and consistently refer to config files relative to your root directory.
wp-load completes its work by loading
wp-config.php. Most of us should be at least a little familiar with this file. It wasn’t too long ago that manual editing of your
wp-config was still a requirement during the install process. Today we all enjoy an automated
wp-config setup as long as our server’s user permissions are configured correctly.
wp-load actually runs through some checks to determine where your
wp-config file is located. This is because you can keep your
wp-config file outside of your root install directory. I’m not sure why you would but I assume it has a lot to do with security. If any one does know, please explain in the comments. If
wp-load fails to find a config file then it throws you a friendly error message with a button to create one.
wp-load successfully located your
wp-config file then this step uses that information to set the last bit of configuration settings before continuing with loading up the WordPress core. The comments at the top of
wp-config sum this step up quite nicely “This file has the following configurations: MySQL settings, Table Prefix, Secret Keys, WordPress Language, and ABSPATH“. I can’t put it any more succinctly than that. After
wp-config is parsed WordPress has all the information it needs to securely access your database and load your content. I’m not sure why
ABSPATH is checked again but it is, it’s the last line of code before ALL the fun begins. The final line of
wp-settings.php which is responsible for loading the lion’s share of WordPress.
Finally some action! Up until now we’ve been wandering through mundane information collection.
wp-settings.php starts off by defining a new constant named
'WPINC'. This constant points to the
/wp-includes directory that was mentioned above. The majority of the predefined functions that WordPress needs for initialization are defined in this directory’s files. After defining
WPINC it requires three files from that directory,
version.php. It’s important to remember that WordPress is not actually executing these functions. They are being included using the PHP function
require(), which makes their contents available to WordPress’ execution environment so the functions they contain can be called when they’re needed.
load.php includes the following functions that are required to properly setup WordPress:
- Turns register globals off
- Fixes $_SERVER variables for various setups
- Checks for the required PHP version, and the MySQL extension or a database drop-in
- This function sends a zero-length favicon header and bails so that the entire WordPress core isn’t loaded when just a favicon is requested
- This function dies with a maintenance message when special “maintenance” conditions are met
- PHP 4 standard microtime start capture
- Returns and/or displays the time from the page start to when function is called
- Sets PHP error handling and handles WordPress debug mode
- Sets the location of the language directory
- Loads the correct database class file
- Sets the database table prefix and the format specifiers for database table columns
- Starts the WordPress object cache
- Redirects to the installer if WordPress is not installed
- Returns array of must-use plugin files to be included in global scope
- Returns array of plugin files to be included in global scope
- Sets internal encoding using mb_internal_encoding()
- Adds magic quotes to $_GET, $_POST, $_COOKIE, and $_SERVER
- Runs just before PHP shuts down execution
- Copies an object
- Checks whether the current request is for a network or blog admin page
- Checks whether the current request is for a blog admin screen /wp-admin/
- Checks whether the current request is for a network admin screen /wp-admin/network/
- Checks whether the current request is for a user admin screen /wp-admin/user/
- Checks whether Multisite support is enabled
- Retrieve the current blog id
- Attempts an early load of translations
Once those essential functions have been loaded
wp-settings loads six more functions from
default-constants.php that will be used to ensure that the global environment for further initialization can be configured properly. The list below outlines these six functions and the constants they define.
- Defines initial WordPress constants
- Defines plugin directory WordPress constants
- Defines cookie related WordPress constants
- Defines cookie related WordPress constants
- Defines functionality related WordPress constants
- Defines templating related WordPress constants
version.php is loaded which provides the following six variables:
- The WordPress version string
- Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema
- Holds the TinyMCE version
- Holds the cache manifest version
- Holds the required PHP version
- Holds the required MySQL version
Now we’re cookin’!! The next 40 lines of code in
wp-settings call many of the functions included above.
wp_initial_constants() is run to setup memory, debug and caching constants;
wp_check_php_mysql_versions() makes sure that we’re running the minimum required versions of both PHP and MySQL; magic quotes are disabled because they will be added later; the default timezone is set; the
wp_unregister_GLOBALS() function is executed to disable PHP’s register globals setting;
wp_fix_server_vars() fixes various $_SERVER related problems across different hosts;
wp_favicon_request() ensures that the entire WordPress core isn’t loaded when only a favicon is being requested;
wp_maintenance() (a very cool function) checks to see if there is a .maintenance file in your
ABSPATH that was created less than 10 minutes ago, if there is it displays a default maintenance message that can be overridden by placing a custom
maintenance.php file in your
timer_start() loads the timer;
wp_debug_mode() checks to see if debugging is enabled and turns on PHP’s error reporting if it is; the
WP_CACHE constant is checked and if it returns true then
/wp-content/advanced-cache.php is included; and finally
wp_set_lang_dir() sets the path to the language files.
WP_CACHE constant is used by 3rd party caching solutions like W3TC, WP Super Cache or Batcache. If
WP_CACHE returns true then
advanced-cache.php acts as the “bootstrapper” to load the caching engine you’re using (thanks to Mark Jaquith for that info).
At this point we have a pretty solid foundation for WordPress to build the rest of it’s initialization on top of. Now it’s time to load some the core files that provide WordPress’ true functionality. Next up
wp-settings requires five more files that it classifies as “early WordPress files”. They are
compat.php, functions.php, class-wp.php, class-wp-error.php and plugin.php. All of these are located in the
/wp-includes directory. While these may be early WordPress files they shouldn’t be underestimated. A tremendous amount of the functionality we expect from WordPress is provided in these five files. They are long and complex,
functions.php alone is over 4,500 lines! I am not going to go into the details of each file’s functions the same way I did above. I will, in future posts, address each of these files individually to give them the attention they deserve. I am after all writing this post (and future posts) to learn more about the core myself. The descriptions below have been taken directly from the source code comments on Trac. It’s more important for this post to focus on the overall initialization of WordPress so I’ll just outline these functions here:
- WordPress implementation for PHP functions either missing from older PHP versions or not included by default.
- Main WordPress API
- WordPress environment setup class.
- WordPress Error API. Contains the WP_Error class and the is_wp_error() function.
- The plugin API is located in this file, which allows for creating actions and filters and hooking functions, and methods. The functions or methods will then be run when the action or filter is called.
- Part of the WordPress translation and localization sub-system. I don’t know a whole lot about localization and translation so I will link to this page I found on the Codex and leave further investigation to the reader.
Now that the baseline functionality of the above files has been loaded
wp-settings moves on to call three more of the functions that were included in
wp-load above. First
require_wp_db() is called to load the DB class and set up the global
$wpdb object. It accomplishes this by requiring
/wp-includes/wp-db.php and then
/wp-content/db.php if it exists.
wp-db.php is another one of those files with over 1,000 lines of code. I will in the future dedicate a post to it alone. For the purposes of this article it’s only important to understand that
wp-db.php is an abstract class file for accessing a MySQL database. The reason that
require_wp_db() tries to require
/wp-content/db.php is because you can define your own database class to access your WordPress database by extending
wp-db.php and placing that code into the
require_wp_db() finishes up by creating the
$wpdb object using the database credentials defined in your
wp-config file. Next
wp_set_wpdb_vars() furthers the setup of the
$wpdb object by setting the field types for the table columns and the table prefix. The
$table_prefix variable defined in
wp-config is added to the
$GLOBALS array just prior to this step so WordPress knows exactly which tables it can access. Finally,
wp_start_object_cache() is called. It’s a little similar to
require_wp_db() in that it’s responsible for loading an abstract class file. In this case its the WordPress Object Cache API. This class is responsible for caching database objects in memory to speed up frequent queries sent to the database.
wp_start_object_cache() first checks to see if there is a file named
/wp-content/object-cache.php because (like
/wp-content/db.php) you can define your own object cache file or class. If
/wp-content/object-cache.php then WordPress’ internal object cache WILL NOT be loaded. If there is no
/wp-content/object-cache.php then the default cache file
cache.php is loaded.
Next up the
default-filters.php is required from the
/wp-includes directory. The
default-filters.php file adds many (but not all) of the default filters and actions to the WordPress Hooks system. This file goes hand-in-hand with
plugin.php that was loaded above. Together these two files prepare the WordPress Plugin API. Anyone interested in plugin development should read through the Plugin API on the codex and have at least these two files open while reading it.
I’m going to group the next 17 lines of code together because after they’re executed we’ll be about halfway through
wp-settings.php and moving into loading a huge chunk of the WordPress core files and functionality. After
default-filters.php is loaded
wp-settings checks to see if we are running multisite. If we are then it loads
/wp-includes. These two files act like
wp-settings.php but handle setup specific to sites that have MultiSite enabled in
wp-config.php. I don’t have any experience with MultiSite at this time but I plan on researching it in the future. At that time I will post an article similar to this one that concentrates on how multisite is initialized. Next, the value of
SHORTINIT is evaluated and if it’s true then initialization is halted at this point. This constant was defined in the
wp_initial_constants() function declared in
default-constants.php above. In that file, it’s default value is set set to false. There may be times that you need access to WordPress without loading all of it’s functionality, e.g. using it as a file serving proxy in MultiSite mode. Setting this constant to true allows you to halt initialization and only use the limited functionality loaded up to this point (thanks again to Mark Jaquith for this info). An additional file related to localization and translation:
/wp-includes/l10n.php, is required next and finally
wp_not_installed() is called to run the installer if we’ve reached this point and WordPress hasn’t been installed. This function was defined in
load.php and runs a few checks to see if certain variables and functions have been defined. If they haven’t, that means WordPress isn’t installed and the initialization process dies; at which point you are redirected to the installer
With those 17 lines of code out of the way
wp-settings moves on to loading the majority of the remaining core files. The following list is long and each file listed is even longer. Just as above, I am going to list them with brief descriptions and link to each file on Trac. Many of the following files deserve their own posts and I will tackle them as time permits. These 40 files constitute the majority of WordPress’ core functionality.
- A class for displaying various tree-like structures.
- Send XML response back to AJAX request.
- Main WordPress Formatting API. If you’ve ever wondered how WordPress replaces your double-line breaks with paragraph elements or inserts the smiley faces in your blog posts, this is the file that does it. This file is also responsible for changing all references to ‘WordPress’ to the proper capitalization.
- WordPress Roles and Capabilities.
- WordPress Query API. Responsible for creating the WP_Query object that allows your front end to talk to the database on the backend. Think: The Loop
- Theme, template, and stylesheet functions. Defines the functions necessary to control your theme(s) as well as the functions that make the Template Hierarchy possible.
- This file defines the WP_Theme class, which helps developers interact with a theme.
- Functions designed to easily retrieve the path to a template are defined here.
- WordPress User API – Responsible for user authentication.
- Metadata API. Allows you to add information to your database to describe objects that are stored there.
- General template tags that can go anywhere in a template. All of your template tags like get_header() and get_footer() are defined here.
- WordPress link template functions. Defines the template tags that are dedicated to navigation between posts. It defines functions like next_posts(), previous_posts() and the_permalink().
- Author template functions for use in themes. Defines the functions that get info about the post’s author. These functions must be used inside The Loop.
- Post functions and post utility functions. Defines all the functions necessary for creating, editing and controlling posts.
- WordPress Post Template Functions. The functions needed to retrieve post information while in The Loop are defined here.
- WordPress Post Thumbnail Functions. The functions needed to retrieve post thumbnail information A theme’s
add_theme_support( 'post-thumbnails' )to use these.
- WordPress Category API. Defines functions for managing category details.
- Category Template Tags and API. Defines functions for accessing category details through template tags.
- Defines functions for managing comments.
- Defines functions for accessing comment details through template tags. These are the functions used in The Loop.
- WordPress Rewrite API. This library of functions handles the creation of “pretty URLs” like /%category%/%postname%/.
- WordPress Feed API. These functions are designed to be used in The Loop to access and manipulate your site’s RSS/ATOM info.
- Link/Bookmark API. Functions for creating and manipulating bookmarks (blogroll links) in the database.
- Defines bookmark template tags for usage in themes.
- HTML/XHTML filter that only allows some elements and attributes.
- WordPress CRON API. These functions allow you to create either one-time or scheduled recurring processes that are triggered and executed when someone visits your site.
- Deprecated functions from past WordPress versions (functions come here to die).
- WordPress scripts and styles default loader. These functions load all the JS and CSS that WordPress needs to create and run the admin area.
- WordPress Taxonomy API.
- A set of functions to check the update service.
- Canonical API to handle WordPress Redirecting. These functions make sure that proper SEO practices are enforced in your site’s URLs and even attempts to guess the correct post/page to load if a visitor types in an incorrect URL.
- WordPress API for creating bbcode like tags or what WordPress calls “shortcodes.”
- API for easily embedding rich media such as videos and images into content.
- WordPress API for media display. Contains the functions WordPress uses to access, edit and display images throughout your site.
- Simple and uniform HTTP request API.
- Simple and uniform HTTP request class.
- API for creating dynamic sidebar without hardcoding functionality into themes. This class and the functions it defines are what make creating sidebars and widgets in plugins and your theme’s
functions.phpfile so easy.
- Navigation Menu functions. All the code necessary to create, control and remove menus in the WordPress admin.
- Navigation Menu template functions. All the code necessary to display menus in a WordPress theme.
- This code handles the building and rendering of the Admin Bar.
Note: If you’d like to read a little more about the inner workings of the Admin Bar (now officially called the Toolbar), check out my first freelance article over at WP Smashing Magazine: Inside The WordPress Toolbar.
Just from reading through these files one at a time I estimate that roughly 75% of the WordPress core has been loaded and we’re about half-way through the
wp-settings file. After all the
require() statements above
wp-settings does another check to see if we’re running multisite. If we are then it requires three additional files:
ms-deprecated.php. These are the MultiSite (formerly WordPress MU) versions of some of the files loaded above. After this check for MultiSite the function
wp_plugin_directory_constants(), which was defined in
default-constants.php, is executed. It sets up seven constants for plugins to use. Now that those constants have been created a
foreach() loop is run to include what are known as “must use” plugins. Back in
load.php a function named
wp_get_mu_plugins() was defined. That function reads the location of the
WPMU_PLUGIN_DIR constant (which by default is set to
/wp-content/mu-plugins) and loads any plugins that it finds. Once that’s done there is another check to see if we’re running MultiSite. If we are then another
foreach() loop is executed to include the
wp_get_active_network_plugins() function. This function is defined in
ms-load.php and loads any MultiSite related plugins that are needed now from the
WP_PLUGIN_DIR constant, which by default is set to the
ms-load.php was included by the
ms-settings.php file. Now that the majority of the Plugin API has been setup the
do_action( 'muplugins_loaded' ) hook is executed.
wp-settings then moves on to call two more of the functions defined in
wp_ssl_constants() are responsible for guaranteeing that we have unique hashes for our cookies and whether or not to force admin and login SSL connections respectively. Once the cookies and SSL settings have been set the file
vars.php is required. This is actually a really cool file and I had no idea that this functionality existed in WordPress until I popped it open.
vars.php starts by setting the
$pagenow variable which always holds the location of the page that’s currently being viewed. After that it tests to see what browser is being used to view the page and stores that in one of a series of nine possible variables:
$is_iphone. How ’bout them apples!! If you’ve ever wanted to serve custom content to your visitors based on their browser from inside your template files these variables allow you to do just that. After the browser detection,
vars.php runs a few checks to determine what server software WordPress is running on, either Apache or IIS. Finally, it finishes up by setting one final variable:
$is_mobile. The variable is a boolean value (true|false) which will be set to true if the value of
$_SERVER['HTTP_USER_AGENT'] matches any of the most common mobile browsers. Pretty fun stuff from a file of only 97 lines!
wp-settings fires off two more functions.
create_initial_taxonomies() (which is defined in
create_initial_post_types() (which is defined in
post.php). The first sets up and initializes the default WordPress taxonomies and the second sets up the default post types (post, page, etc.). There is a warning in
wp-settings alerting all you developers out there that the defaults in these two files will be run again on the init hook that executes at the end of
wp-settings. Taxonomies are how WordPress organizes information internally. We are all familiar with the two most notable taxonomies already: categories and tags. Custom taxonomies were introduced in v2.3 and updated in v2.8 and v3. There is a great article from Justin Tadlock on custom taxonomies in v2.8 here and another from NetTuts on v3 custom taxonomies available here. If you’ve looked at the admin area of any decent theme you know that there are usually options to change the “type” of post (e.g. – aside, quote, gallery, etc.). Those defaults are all created in the
create_initial_post_types() function. v3 of WordPress added the ability to create custom post types. Here’s another great article from Justin Tadlock on custom post types in v3.
At this point most of the core, the Plugin API, taxonomies and post types are loaded so
wp-settings starts loading the active theme. It does this by executing
register_theme_directory() and passing in
get_theme_root() as an argument. Both of these functions were defined in
theme.php. They are responsible for determining the location of and loading the active theme’s directory. Once the active theme’s directory has been loaded
wp-settings loads all active plugins by running a
foreach() loop to step through each plugin found by running
wp_get_active_and_valid_plugins(). This function (defined in
load.php) looks through
/wp-content/plugins and returns any valid plugins that it finds. After the active plugins are loaded two new files are required.
pluggable-deprecated.php include useful functions for working with logged in users, sending mail and getting/setting user info. They are defined and required at this point so they can be overridden by any plugins loaded through the upcoming
do_action( 'plugins_loaded' ) hook. The
pluggable-deprecated.php file is included to maintain backward compatibility but obviously none of those functions should be used because they will be removed in a future version. The default encoding is set next by running
wp_set_internal_encoding() which was defined in
load.php, it defaults to UTF-8. Now a quick check is made to see if the constant
WP_CACHE is set to true and if the
wp_cache_postload() function exists. If it does then it gets executed to setup any remaining caching related functionality that had to wait until more of the core was loaded. At this point the entire Plugin API is up and running so the
do_action( 'plugins_loaded' ) hook is fired to enable plugin developers to execute any custom functionality provided in their plugins when they’re loaded.
wp-settings now fires off
wp_functionality_constants(), defined in
default-constants.php, sets the
AUTOSAVE_INTERVAL, EMPTY_TRASH_DAYS and WP_POST_REVISIONS constants to handle the housekeeping for your posts.
wp_magic_quotes(), defined in
load.php, takes all the variables from
$_GET, $_POST, $_COOKIE and $_SERVER and sanitizes them by running
add_magic_quotes() and then adds them to an array that gets assigned to
$_REQUEST. Then the
do_action( 'sanitize_comment_cookies' ) hook is executed.
The next section of
wp-settings handles the creation and setup of some pretty important objects. First it creates a new WP_Query object and assigns it to the variable
$wp_the_query. Then it creates another variable that points to a reference to that variable called
$wp_query. This is the default loop that you’re accessing when you run
if (have_posts()) : while (have_posts()) : the_post();. After that’s done it creates the WP_Rewrite object (defined in
rewrite.php for handling permalinks) and assigns that to the global variables array in
$GLOBALS['wp_rewrite']. Then it creates a new WP object (which was defined in
class-wp.php and is responsible for creating the whole WordPress environment) and assigns it to the variable
$wp. Next it creates a new WP_Widget_Factory object and assigns that to the global variables array at
$GLOBALS['wp_widget_factory'], and finally creates a new WP_Roles object, assigning it to the global variables array at
$GLOBALS['wp_roles'] Once all those tasks have competed the hook
do_action( 'setup_theme' ) is executed to allow plugins to take action right as a theme is getting ready to be loaded.
wp-settings moves on to setup a few environment requirements for getting our theme loaded. The function
wp_templating_constants() (defined in
default-constants.php) is executed at this point. This function is responsible for creating the constants familiar to theme designers,
STYLESHEETPATH. In addition, it checks to see if the
WP_DEFAULT_THEME constant has been set and if not it sets it to (currently) twentytwelve. This default theme is used for any new install of WordPress as well as if the current theme somehow goes missing. After that function the
load_default_textdomain() function is run to ensure that proper language settings are loaded. Once the default text domain has been set the default locale file is determined and required. Once both of those steps are complete a WP_Locale object is created and assigned to the global variables array at
$GLOBALS['wp_locale']. Anyone interested in how WordPress handles so many multiple languages or wants to help WordPress support more languages, these are the files you want to study.
We are so close to the end I can taste it! This next chunk of code will be interesting to any parent/child theme designer who wonders why a child’s
functions.php file is loaded before the parent’s, but all the parent’s template files are loaded before the child’s. I know I always have. After the locale is setup
wp-settings runs through an if statement checking the values of
STYLESHEETPATH is different than
TEMPLATEPATH it loads it’s
functions.php first then it calls the one in
TEMPLATEPATH. I guess if you think it through it makes sense. You want the child to be able to set up any custom functions before the parent can define them. This is why parent themes should check if a function exists before executing it, just incase the child has defined a custom one. Once that code executes
wp-settings calls the
do_action( 'after_setup_theme' ) hook for any themes or plugins that need to execute custom code when a theme is done with its setup. The init method of the $wp object is called next to setup the current user’s settings and the hook
do_action( 'init' ) is run. This is just about it folks, there is only one more check for MultiSite and then the hook
do_action( 'wp_loaded' ) is run for any theme or plugin that needs to run any code once WordPress’ core has fully loaded. As the curtain sets on
wp-settings the WordPress core has completed loading and execution returns to
wp-blog-header.php. I know, it feels like we left that file a few days ago! It always amazes me that all of the functionality we just covered loads in mere seconds while the request is being processed.
If you’ve made it this far I would just like to congratulate you. We’re almost done! Lets just do a really quick recap of where we are at this point. When the visitor’s browser sent our server a request
WP_USE_THEMES to true and required
wp-blog-header.php. That file first called
wp-load.php, then it executes the function
wp() and finally requires
wp-load.php defined the
ABSPATH constant and grabbed the site’s configuration settings from
wp-config.php before calling
wp-settings.php (the majority of this article, which we just covered) handled the loading of all core functionality, plugins and the active theme. Now that
wp-settings.php is complete and execution has returned to
wp-blog-header.php we can move on to the conclusion of our tour through WordPress’ initialization.
wp-blog-header.php now executes a function defined in
wp(). If you weren’t paying attention, about 3/4 of the way through
wp-settings.php a global variable named
$wp was defined and instantiated as a WP object (that WP object was defined in
class-wp.php). This object is responsible for controlling the entire WordPress environment after it’s been loaded. The
wp() function called by
wp-blog-header.php finalizes the setup of this object by calling its
main() function. This effectively puts the finishing touches on the global WordPress environment and also ensures that the current query has been properly configured so The Loop works the way we all expect it to. I gotta give one final shout-out to Mark Jaquith for pointing me to the info on this function. I’m tellin’ you this guy is a badass! If you don’t follow him on Twitter, do yourself a favor and follow him now. I’ll just say this, that thing on his shoulders ain’t just a hat rack my friends!
We can now finally display a page to our visitor! The
template-loader.php file is responsible for determining not only what template should be used for displaying the content but also what kind of visitor our server is responding to. If this request is for a robot, a feed or a trackback then it serves the appropriate content for those requests. If the current request is from a robot then it calls the
do_robots hook. This hook is defined in
functions.php and serves a robots.txt file when called. If the request is for one of our feeds then the function
do_feed() is called (also defined in
functions.php) and then serves whichever feed format has been requested. If the request is a trackback or pingback then the
wp-trackback.php file is required. This file runs through some fancy checks and then builds the response which is served back based on whether a trackback or pingback request was received. If the request is for anything other than what we just covered then WordPress steps through a 25 line elseif statement to determine the type of template to load. This is how the Template Hierarchy is implemented in WordPress. There’s a great overview of the template hierarchy, written by Chris Coyier, over at his (and Jeff Star’s) Digging into WordPress site. I highly recommend that site in general, loads of great tips and tricks!
WHEW!! Well, if you think about it, everything we just covered is what happened when you clicked whatever link brought you to this post. It’s taken me a lot longer than I expected to write this; my back hurts and I really need to get back to learning some Ruby programming! 🙂 So I’m just going to thank you if you’ve made it to the end. Thank you for sticking with me. I hope you’ve learned as much reading this as I did writing it. I intend to be back soon with a (shorter) post on a more specific topic.
68 thoughts on “WordPress Initialization”
Whoa.. really good job Dominic 🙂
About the wp-config.php, as you can see here http://codex.wordpress.org/Hardening_WordPress#Securing_wp-config.php it is recommended to move the file in a non public area of your website just as one more security measure.
Thanks for including the link to the Codex so others can learn as well. I’m glad you liked the post.
It would be great if you can create some illustrations for the initializing process.
Thats an excellent idea. I’ll see what I can do about adding illustrations and also including them in future posts.
It seems Ziming is on it:
There is another chart, sequence diagram.
It’s a good practice to keep the config file out of the www accessible folder in case any other secure aspect of your site is compromised and the root folder is somehow opened up to http access. Because this file contains authentication credentials, including database credentials and sometimes even ftp authentication info, the results of having this file compromised could be catastrophic. Placing it outside the http path addresses this contingency.
That’s what I was thinking while writing this post but since I wasn’t exactly sure I figured I’d ask for comments. Thank you very much for taking the time to comment.
ooooohhhh!!!! looks great. Tks for your work!!!
[…] humanshell.net has a very thorough walk-through of what the code does when a page is called. […]
Thank you. Will definitely put this to use when developing plugins 🙂
Great job dominic. It added a lot to knowledge.
[…] Very useful: WordPress initialization steps: what gets loaded and in what order […]
Really Great job dominic…
keep it up
Great writeup:) Now if we could get this into a cheat-sheet I’d be totally sold:D
Excellent post. I’ve been working with WordPress for five years and still didn’t know much of this. Thanks Dominic
Dominic, just added a link to this post on the Codex Query Overview page: http://codex.wordpress.org/Query_Overview
Great article! It will help mi to better understand wordpress.
[…] Next, every WordPress theme also has a functions.php file that is executed for every pageload, so this is where my common code will reside. I believe functions.php is executed before the appropriate template file. The initialization, which isn’t documented formally, is described in this article the WordPress bootstrap. […]
I’ve been looking for this kind of article the past few months. This GREAT article gives me a clearer view of how WP really works.
Great job Dominic! I really like this article.
[…] When a visitor first clicks on or types a URL for a page that is part of your blog, WordPress starts by running a few core files (wp-config.php, wp-settings.php, etc.) If you are interested in the specifics of the file loading order, start at index.php and follow the chain of files as each PHP file includes/requires additional PHP files (or read this excellent post at humanshell.net) […]
[…] WordPress Initialization. Kolejny bardzo informatywny wpis analizujący proces "działania" WP. […]
[…] 100 of my fellow ‘pressers turned out for the event. The presentation was adapted from my recent post on the same […]
This is exactly what I was looking for! Thanks a lot!
dude great job!!
Wow, this is soooo comprehensive! Thank you so much. Graphics would be great, but who has a double A0 printer for all that information at home? Maybe you could create a wallpaper (a real physical thing)?!? 🙂
Just for understanding: this whole process is run on every page refresh and every time I load a WordPress page?
To the best of my understanding this process is run through for every request. However, if you look closely at wp-blog-header.php you’ll see that it only kicks off the initialization if $wp_did_header IS NOT set (that’s what !isset($wp_did_header) means). I assume that conditional statement is an attempt to cut down on the amount of times your site needs to run through the init process. But don’t quote me on that, there is still much about the init process that I have to learn.
My understanding is every single request will go through this process, or nowhere to write the output to visitors.
This is an excellent resource, both for experienced and newbie WordPressers alike. Understanding just how this all hangs together is a real help to building good themes, I haven’t manged to do that yet but this has helped greatly in getting me along that road. Many thanks
Its truly amazing how people waste so much time pondering over crap code that began life in a mess.
Thanks for such great post! Learnt a lot!!!!
Absolutely incredible. I look forward to future posts. Love the article.
[…] http://humanshell.net/wordpress/wordpress-initialization/ Share this:EmailPrintLike this:LikeBe the first to like this post. CMS – WordPress ← – […]
[…] dev team. Dom is a student in Computer Science at BMCC. He’s known in the WordPress world for a popular blog post explaining the WP initialization process, as well as for his contributions to the WordPress section of Smashing Magazine. Dom’s […]
[…] dev team. Dom is a student in Computer Science at BMCC. He’s known in the WordPress world for a popular blog post explaining the WP initialization process, as well as for his contributions to the WordPress section of Smashing Magazine. Dom’s […]
[…] everyday. The result of studying this process, line by line in the files involved, culminated in a blog post that basically introduced me to the WordPress community. One of the core developers of WordPress, […]
Whoa, great article, lot time looking for something like this, Thanks a lot
[…] Take a look at the Complete WordPress Initialization Flowchart, or if you’re in the mood for reading a really long (but very good) description of it, check out this article on humanshell.net. […]
[…] explored the internals of the WordPress initialization process extensively and I’ve presented at the monthly WordPress NYC Meetup. You can see examples of […]
[…] WORDPRESS INITIALIZATION […]
[…] http://humanshell.net/2011/08/14/wordpress-initialization/ (text) […]
I feel very humble. I am beginner in the wordpress. I am reading and attempting to develop my first theme. I have been wishing to go through wordpress loading process the way you do in this post. But, I am lucky I didn’t start before searching for such thing which led me to this post. I went through the whole content, yet I will go through it multiple times until I get good understanding of it. Really great post!
Also, thank you for introducing the “badass”. You are also an other “badass” (never used this term before, I am
Thank you so much.from the other country and forgive me if I am not using it right).
Just one minor thing, Somewhere in the post is read as “… wp_not_installed() is called to run the installer if we’ve reached this point and WordPress hasn’t been installed. This function was defined in wp-load and runs a few checks to see if certain variables and functions have been defined..”
But, I believe function wp_not_installed() is defined within load.php not within wp-load.php.
You are correct, excellent catch! I’ve updated the post to correct this error.
[…] http://humanshell.net/2011/08/14/wordpress-initialization/ […]
[…] I spend most of the time reading WordPress initialisation artikel. I learned a lot even I’m not finish yet. I also started with WordPress Theme Development […]
[…] I finished WordPress from Request to Response and WordPress Theme Development Training. I feel ready to go to the next step (Vulnerability […]
I really found this post , Solar Shade “WordPress
Initialization | $(“humanshell”).net()”, really enjoyable and the post was a good read.
Wanna thank you for the great article, it helped me a lot 🙂
[…] this article I know wp-load.php, it will init the WordPress environment (wp-config.php, […]
Very Very Very good and extremely necessary post for a WordPress newbie …Thanks a lot
This website was… how do I say it? Relevant!! Finally I have found something which helped me.
[…] A very long and deep article: http://humanshell.net/2011/08/14/wordpress-initialization/ […]
Thanks for your marvelous posting! I really enjoyed reading
it, you are a great author.I will be sure to
bookmark your blog and may come back in the future. I want to encourage one to continue your great writing, have a nice afternoon!
Wow! After all I got a website from where I be able to
genuinely obtain useful data regarding my study and knowledge.
[…] WordPress Initialization […]
Have you ever thought about including a little bit more than just your articles?
I mean, what you say is valuable and all. Nevertheless think of if you added some great visuals or videos to give your posts
more, “pop”! Your content is excellent but with pics and videos, this blog
could undeniably be one of the very best in its field.
Fantastic blog! Much appreciated!