I think the earliest actions you can hook are muplugins_loaded
and plugins_loaded
. muplugins_loaded
will only fire for Must Use Plugins.
Some plugins_loaded
pseudo-code:
add_action( 'plugins_loaded', 'wpd_plugin_routes' );
function wpd_plugin_routes() {
if( is_a_virtual_file() ){
serve_file();
exit;
}
}
If you want the full WordPress environment, plugins, theme, and authenticated user, right before WordPress parses the request, you’ve got the do_parse_request
filter:
add_filter( 'do_parse_request', 'wpd_do_parse_request', 1, 3 );
function wpd_do_parse_request( $continue, WP $wp, $extra_query_vars ){
// do something and halt execution, or
return $continue; // true by default, meaning continue parsing the request
}
If you want all of the above after WordPress parses the request, you’ve got the parse_request
action. Here you can alter the main query vars:
add_action( 'parse_request', 'wpd_parse_request_thing' );
function wpd_parse_request_thing( $query ) {
if( isset( $query->query_vars['pagename'] ) ){
if( 'some-page' == $query->query_vars['pagename'] ){
$query->query_vars['pagename'] = 'some-other-page';
}
}
}
The last action right before the template is loaded is template_redirect
. Here all of the is_
conditionals work:
add_action( 'template_redirect', 'wpd_page_template_redirect' );
function wpd_page_template_redirect() {
if( is_404() ) {
// do something
die;
}
}