This is my interpretation in pseudo code of the WP class in Wordpress. I did this mainly to know what's going on under the hood. If you get anything of value from it, great.
wp-config.php
When Wordpress boots up, wp-settings.php is included from the wp-config.php file:
The WP class is instantiated once within the wp-settings.php file. The instance exists as a global variable, $wp, throughout the system.
. $wp = new WP(); .
This is a snapshot of the WP Class as of Wordpress 3.3.1, March 11, 2012. All variables and methods are made public. The meat of the WP Class framework consists of:
class WP { var $public_query_vars = array(); var $private_query_vars = array(); var $extra_query_vars = array(); var $query_vars; var $query_string; var $request; var $matched_rule; var $matched_query; var $did_permalink;
function add_query_var($qv) {} function set_query_var($key, $value) {} function parse_request($extra_query_vars) {} function send_headers() {}; function build_query_string() {} function register_globals() {} function init() {} function query_posts() {} function handle_404() {} function main() {} }
First thing to note is there are two arrays with one for private and the other for public query variables.
Public Query Variables
Publicly available query variables that you can access directly from the $wp variable. By public I believe this means what can be typed into the user agent's address bar (like mysite.com/?m=something&p=something):
m
p
posts
w
cat
withcomments
withoutcomments
s
search
exact
sentence
debug
calendar
page
paged
more
tb
pb
author
order
orderby
year
monthnum
day
hour
minute
second
name
category_name
tag
feed
author_name
static
pagename
page_id
error
comments_popup
attachment_id
subpost
subpost_id
preview
robots
taxonomy
term
cpage
post_type
Private Query Variables
The private query variables are only used in the parse_request() call. You must set extra_query_vars and they must match with the same named private_query_vars to get pass through and get set. This ensures that named variables outside this space does not get injected into the query_vars space.
foreach ( (array) $this->private_query_vars as $var) { if ( isset($this->extra_query_vars[$var]) ) $this->query_vars[$var] = $this->extra_query_vars[$var]; }
offset
posts_per_page
posts_per_archive_page
showposts
nopaging
post_type
post_status
category__in
category__not_in
category__and
tag__in
tag__not_in
tag__and
tag_slug__and
tag_id
post_mime_type
perm
comments_per_page
post__in
post__not_in
add_query_var($qv)
Very simple code that adds a string to the public query variables array. First checks if the string exists in the array and then adds it if it doesn't exist. Note that this just adds the query variable name to the array. It does not set it with a value.
// if query variable string name is not in the public query variable array if (!in_array($qv, $this->public_query_vars)) $this->public_query_vars[] = $qv; // add it
set_query_var($key, $value)
Creates a key and sets the value to a query variable in the query vars array (not the public_query_vars)..
$this->query_vars[$key] = $value;
main($query_args='')
This is where the processing for a request begins.
Initialize thyself Parse a request Send HTTP headers Run the query to fetch posts Setup a 404 header if didnt find anything else setup a HTTP 200 header Register globals (not PHP globals but Wordpress. These are just date stuff and deprecated) Setup the "wp" action to execute all action (not filter) hooks
handle_404()
This is for handling a 404 error (page not found). There is a lot of logic in this handler and most of it won't make sense unless you truly understand the bowels of the system. Basically this will check to see if any posts were returned from a query and a bunch of other tests based on.
handle_404 is only called from main() after query_posts(). At this point, Wordpress either found something or not for the given request. This function will setup a HTTP 200 Success or HTTP 404 headers.
if not in admin mode, the number of posts is 0, are not on an existing 404 page, query string ['robots'] not robot, query string['s'] not set as a search page and not home page { if a tag, category, taxonomy, author, post archive, queried object, not paged { if not 404 return a HTTP 200 Success } set 404 flag return a HTTP 404 not found status } else if is not a 404 return HTTP 200 Success
init()
The init function basically just makes one call, wp_get_current_user() which instantiates a user. Doesn't really make much sense to me for a user to be instantiated in a WP object. More so when there is no $user variable within the class to hold it.
query_posts()
This function builds the query string and invokes the query based on the public query_vars. Notice we get a hint here that there is a $wp_the_query variable lying around.
global $wp_the_query; $this->build_query_string(); $wp_the_query->query($this->query_vars);
This is the global Wordpress system variable that gets instantiated in wp-settings.php. It is an instance of WP_Query.
$wp_the_query->query() basically parses the query string and then calls get_posts() that does all the post processing.
send_headers()
Although I don't fully understand all the gyrations on this one, this is what I gather:
Sets up HTTP headers for some esoteric stuff and exits
Same as above and gives listeners opportunity for send_headers action
The esoteric stuff is for:
if user is logged in, a string is returned for HTTP headers to not cache
if it is a 404 error set to not cache and set content-type and character set
if a rss feed set content-type and character set
Setting last modified date
Checking HTTP_IF_NONE_MATCH, HTTP_IF_MODIFIED_SINCE for a HTTP 304
build_query_string()
Builds the query string based on the public query_vars of the WP class by iterating through each key/value pair and building query strings behind the scenes:
It also makes a call to the query_string filter but this is deprecated. Instead, one should use the request filter instead. I kind of think this is a great place to do some debugging if you are a theme or plugin developer in this filter. You can do stuff like the following to get information right before the call to hit the database. You can put this in your functions.php file:
function request_filter_hook($request) { global $wp; global $wp_query; global $debugTheme;
if (true == $debugTheme) { // interrogate to see whats available echo "<h2>Dump of request variable</h2>"; var_dump($request);
echo "<h2>Dump of wp_query variable</h2>"; var_dump($wp_query);
echo "<h2>Dump of wp variable</h2>"; var_dump($wp); } return($request); }
This is the workhorse that parses an HTTP request.
Create empty query_vars and post_type_query_vars arrays
// Handle $extra_query_vars and represent as an array If extra_query_vars was passed in as an array then reference it else treat it as a string like search?item1=foo&item2=bar convert to an array $extra_query_vars(item1=>foo, item2=>bar)
// care of path_info, request_uri, and 404 Get the rewrite rules Assume by default we can't find anything and it is a HTTP 404
Breakup PATH_INFO into variable parts Breakup REQUEST_URI into variable parts Breakup PHP_SELF into variable parts
Get the home url and strip off the trailing slash Exclude the home url in these strings leaving only folder/title REQUEST_URI PATH_INFO PHP_SELF Sets $wp's request variable Iterate through the internal rewrite rule list to find a match with the request if there is a match grab only the query string part (i.e. ?blah=something&blah2=something2) do some reg expression magic to substitute strings in the query parse the into an array (i.e. $a("blah"=> 'something', "blah2"=> "something2"))
transfer extra_query_vars to query_vars apply filters on request for the query vars announce to listeners parse_request
Summary
Phew! That was quite a long article but if you got something out of it, thats terrific. I sure did and picked up a few things that I can use along the way as well.