admin管理员组文章数量:1122826
My goal is a redirect to a custom template based on some new rewrite rule, but without having wordpress to make unusefull queries.
my code:
function add_rewrite_rules() {
add_rewrite_rule(
'^settore/([^/]*)/?$',
'index.php?settore=$matches[1]',
'top'
);
add_rewrite_tag('%settore%','(caldareria|tessile)');
}
add_action( 'init', 'add_rewrite_rules' );
function set_root_category_template($template){
$settore = get_query_var('settore');
if($settore != '') $template = locate_template('root-taxonomy.php');
return $template;
}
add_filter('template_include','set_root_category_template',99);
It redirects just right, but if I check $wp_query->posts in root-taxonomy.php, I see a list of regular post. Instead, in that page I'll make a custom query asking for some specific taxonomy terms data, and therefore, the default query is totally useless. How can I stop it? After all, I'm not passing any default query var to index.php so I can't understand the reason why wp is still doing a query..
My goal is a redirect to a custom template based on some new rewrite rule, but without having wordpress to make unusefull queries.
my code:
function add_rewrite_rules() {
add_rewrite_rule(
'^settore/([^/]*)/?$',
'index.php?settore=$matches[1]',
'top'
);
add_rewrite_tag('%settore%','(caldareria|tessile)');
}
add_action( 'init', 'add_rewrite_rules' );
function set_root_category_template($template){
$settore = get_query_var('settore');
if($settore != '') $template = locate_template('root-taxonomy.php');
return $template;
}
add_filter('template_include','set_root_category_template',99);
It redirects just right, but if I check $wp_query->posts in root-taxonomy.php, I see a list of regular post. Instead, in that page I'll make a custom query asking for some specific taxonomy terms data, and therefore, the default query is totally useless. How can I stop it? After all, I'm not passing any default query var to index.php so I can't understand the reason why wp is still doing a query..
Share Improve this question asked Jun 13, 2014 at 9:35 Luca ReghellinLuca Reghellin 1,6402 gold badges21 silver badges45 bronze badges 6 | Show 1 more comment3 Answers
Reset to default 6Stop WordPress to run main query is hard: you have to dig inside the deep heart of WordPress.
WordPress frontend workflow:
wp-blog-header.php
call the functionwp()
wp()
function creates an instance of wp class, and callmain()
method on itmain()
method code:public function main($query_args = '') { $this->init(); $this->parse_request($query_args); // build query vars starting from url $this->send_headers(); $this->query_posts(); // run main query via WP_Query using built query vars $this->handle_404(); // if query has no results set 404 headers and WP_Query props $this->register_globals(); }
wp-blog-header.php
includetemplate-loader.php
that load template file based on query
So only way to stop main query is prevent wp()
to run.
That can be done hooking an early hook, do what you need, and finally exit()
.
The problem of this approach is that preventing wp()
to run, you also prevent wp class to parse request, so the rewrite stuff you add are not parsed.
So, instead of to add a rewrite tag and a rewrite rule, you may want to look straight at the url to choose if it is the one that should trigger your custom action.
First of all let's write a function that return only the relative parte of the url, e.g. if current url is something like example.com/wp/path/to/somewhere?foo=bar
and your home url is example.com/wp/
the function returns path/to/somewhere
:
function get_relative_url() {
$home_path = rtrim( parse_url( home_url(), PHP_URL_PATH ), '/' );
$path = trim( substr( add_query_arg( array() ), strlen( $home_path ) ), '/' );
$qs = array_keys( $_GET );
if ( ! empty( $qs ) ) {
$path = remove_query_arg( $qs, $path );
}
return $path;
}
Now we can use an early hook to look at the url, and only if it contains the desired path we'll set the $settore
variable, load the template and exit:
add_action( 'wp_loaded', function() { // 'wp_loaded' hook happen before wp() is ran
$path = get_relative_url();
$url_parts = explode( '/', $path );
if (
isset( $url_parts[1] )
&& $url_parts[0] === 'settore'
&& in_array( $url_parts[1], array( 'caldareria', 'tessile' ), TRUE )
) {
// ok the current url is something like example.com/settore/tessile
// and 'tessile' is in the variable $url_parts[1]
$template = locate_template( 'root-taxonomy.php' );
if ( empty( $template ) ) return; // do nothing if template not found
global $settore;
$settore = $url_parts[1]; // in the template you can access to $settore variable.
require_once $template;
exit(); // prevent WordPress to do anything else
}
} );
That's all.
In code above, understanding if the current url is the right one, and set the $settore
variable was easy because the url structure was easy, for more complex url structures, you probably need a regex matching, and maybe use a tool like Symfony routing component to match the url to some variables.
This approach is the one I've used in Cortex, have a look there if you plan to commonly do thing like that.
Gotchas
as you can see, the main query (global $wp_query
) in code I posted is not used, in your template it will be an empty WP_Query
object, so anything will refer to main query, e.g. template tags like is_tax()
, is_archive()
or such, will not work.
That will apply to header and footer as well, because very probably in your 'root-taxonomy.php' you'll use get_header()
and get_footer()
.
Also some plugins may not work properly, e.g. if you are using any SEO plugin that set title tag based on the query, than it will have issues.
A possible solution is to manually set main query properties accessing to global $wp_query
or use a custom header, e.g. get_header('root-tax')
, for your custom template and handle in header-root-tax.php
custom title tag and/or any other issue.
why not like this?
add_action( 'pre_get_posts', 'my_post_queries' );
function my_post_queries( $query ) {
if ($query->is_main_query() && !is_admin()) {
// maybe check for specific page here
// if (is_tax('your-taxonomy') {
$query = false;
remove_all_actions ( '__after_loop');
// }
}
}
Or did I misunderstand the question?
Here's what worked for me to avoid unnecessarily running the main query. Place this in your theme's functions.php
file:
add_filter( 'posts_pre_query', 'prevent_main_query_from_running', 10, 2 );
function prevent_main_query_from_running( $posts, WP_Query $Query ) {
if ( $Query->is_main_query() && ! is_admin() ) {
add_filter( 'pre_handle_404', function( $bool, WP_Query $Query ) {
return true;
}, 10, 2 );
return array();
}
return $posts;
}
See this YouTube video for deep explanation.
Note: this will apply to all front end pages, so unless that's what you're trying to accomplish, I would recommend making it more specific, maybe exclusively on a single page you're trying to avoid loading the main query on. For example, to prevent the main query from loading on the home page only, you can change that third line above to
if ( $Query->is_main_query() && $Query->is_home() && ! is_admin() ) {
本文标签: url rewritingHow to stop wordpress to make the default query
版权声明:本文标题:url rewriting - How to stop wordpress to make the default query? 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736303028a1931742.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
template_include
andtemplate_redirect
are fired main query already happen, so using any of the two hooks you can't stop it. – gmazzap Commented Jun 13, 2014 at 11:13