admin管理员组文章数量:1291144
How can I add a custom rewrite rule so I can catch paths like these:
/products/imports/filters
/products/imports/elements
/products/imports/parts
And point them to a template file, for examples:
sector.php
My code:
function sector_rewrite_rule() {
add_rewrite_rule(
'(.?.+?)/([^/]*)/([^/]*)/?$',
'index.php?pagename=$matches[1]/$matches[2]§or=$matches[3]',
'top'
);
}
add_action('init', 'sector_rewrite_rule', 10, 0);
But I get 404 when I tried with the URLs above.
I have created a standard page called imports
created under products
already:
products/
imports/
So I want to catch any word right after this page:
/products/imports/
How can I add a custom rewrite rule so I can catch paths like these:
/products/imports/filters
/products/imports/elements
/products/imports/parts
And point them to a template file, for examples:
sector.php
My code:
function sector_rewrite_rule() {
add_rewrite_rule(
'(.?.+?)/([^/]*)/([^/]*)/?$',
'index.php?pagename=$matches[1]/$matches[2]§or=$matches[3]',
'top'
);
}
add_action('init', 'sector_rewrite_rule', 10, 0);
But I get 404 when I tried with the URLs above.
I have created a standard page called imports
created under products
already:
products/
imports/
So I want to catch any word right after this page:
/products/imports/
Share
Improve this question
edited Jun 10, 2021 at 22:45
Run
asked Jun 10, 2021 at 22:19
RunRun
3315 silver badges20 bronze badges
3 Answers
Reset to default 3You need to create query_var
for sector
and you need to create a rewrite rule with RegEX. I created a plugin for this. Create a file and add into the wp-content/plugins
folder and activate it.
<?php
/*
Plugin Name: Custom Rewrite
Plugin URI: https://serkanalgur.tr
Description: Custom Rewrite
Version: 1
Author: Serkan Algur
Author URI: https://www.serkanalgur.tr
License: GPLv2 or later
License URI: http://www.gnu/licenses/gpl-2.0.html
*/
class FilterRewriteRule
{
public function init()
{
$this->InitRewriteRules();
add_filter('query_vars', [$this,'add_query_for_sector']);
add_filter('template_include', array($this, 'filter_template'), 99);
}
private function add_query_for_sector($vars)
{
$vars[] = 'sector';
return $vars;
}
private function InitRewriteRules()
{
add_rewrite_rule(
'products/import/([^/]*)/?$',
'index.php?pagename=products/import§or=$matches[1]',
'top'
);
add_rewrite_rule(
'products/import/page/([0-9]{1,})/([^/]*)/?$',
'index.php?paged=$matches[1]&pagename=products/import§or=$matches[2]',
'top'
);
}
public function filter_template($template)
{
global $wp;
if (get_query_var('sector') && is_page('import')) {
$custom_template = locate_template('sector.php');
if ($custom_template) {
return $custom_template;
}
}
return $template;
}
}
register_activation_hook(__FILE__, function () {
$writing_ideas = new FilterRewriteRule();
$writing_ideas->init();
flush_rewrite_rules();
});
add_rewrite_rule
add the rewrite rule with pagination support. filter_template
locate your sector.php
file and redirect the request to this file. query_vars
adds sector
query to WordPress system.
An alternate Solution
If you're concerned about the Page slug being changed later on, then you could instead use add_rewrite_endpoint()
, but this means the URL would need an extra path, e.g. /sector
as in example/products/imports/sector/filters
.
So the steps are identical, except that you no longer need to manually hook on query_vars
because add_rewrite_endpoint()
will, by default, do that automatically for you:
Register the
sector
endpoint for all Pages:add_action( 'init', 'my_sector_init' ); function my_sector_init() { add_rewrite_endpoint( 'sector', EP_PAGES ); }
Remember to remove the
add_action('init', 'sector_rewrite_rule', 10, 0);
in your code.. and as I already said before, flush the rewrite rules! :)Load the
sector.php
template on those custom endpoint pages:add_filter( 'page_template', 'my_sector_page_template' ); function my_sector_page_template( $template ) { if ( get_query_var( 'sector' ) ) { $template = locate_template( 'sector.php' ); } return $template; }
Other Option when using add_rewrite_rule()
with a specific Page slug or path
Store the Page ID in a variable (or database option if you want to) and the previous path in a post metadata, and whenever the Page or its parent is updated, specifically if the slug is changed, then you can programmatically flush the rewrite rules.
So based on my original answer, in step 1, we'll call flush_rewrite_rules()
only if applicable:
function sector_rewrite_rule() {
$page_id = 123;
// Ensure that the post exists.
if ( ! get_post( $page_id ) ) {
return;
}
$post_ancestors = get_post_ancestors( $page_id );
$previous_slug = get_post_meta( $page_id, '_prev_path', true );
// Build the hierarchical path.
$post_ancestors[] = $page_id;
$current_slug = implode( '/', array_map( function ( $id ) {
return get_post_field( 'post_name', $id );
}, $post_ancestors ) );
add_rewrite_rule(
'^' . preg_quote( $current_slug ) . '/([^/]+)/?$',
'index.php?page_id=' . $page_id . '§or=$matches[1]',
'top'
);
global $pagenow; // this is defined on admin pages
if ( 'options-permalink.php' !== $pagenow && $current_slug !== $previous_slug ) {
update_post_meta( $page_id, '_prev_path', $current_slug );
flush_rewrite_rules();
}
}
And step 2 remains the same, but step 3 would be (note the $page_id
):
add_filter( 'page_template', 'my_sector_page_template' );
function my_sector_page_template( $template ) {
$page_id = 123;
if ( is_page( $page_id ) && get_query_var( 'sector' ) ) {
$template = locate_template( 'sector.php' );
}
return $template;
}
So you can try those and just replace the value of $page_id
with the correct ID.
Try these steps, which worked well for me:
Use a more specific rewrite rule RegEx pattern like so which ensures the current URL path is in the form of
products/imports/<word>
:function sector_rewrite_rule() { add_rewrite_rule( // matches products/imports/filters, but not products/imports/filters/foo '^products/imports/([^/]+)/?$', // ensure pagename is in the form of <parent>/<child> 'index.php?pagename=products/imports§or=$matches[1]', 'top' ); }
Register
sector
as a public query var via thequery_vars
hook: (public query vars are those that will be read from GET/URL and POST parameters)add_filter( 'query_vars', 'sector_query_vars' ); function sector_query_vars( $vars ) { $vars[] = 'sector'; return $vars; }
Now that the rewrite rule and query var has been both added, we just need to ensure the
sector.php
template is used on theproducts/imports/<word>
endpoints. So since we're targeting a Page (post of typepage
), then I'm using thepage_template
hook, but you could instead use thetemplate_include
hook if you want to:add_filter( 'page_template', 'my_sector_page_template' ); function my_sector_page_template( $template ) { if ( is_page( 'imports' ) && get_query_var( 'sector' ) ) { // this assumes the template is in the active theme directory // and just change the path if the template is somewhere else $template = locate_template( 'sector.php' ); // use a full absolute path } return $template; }
Remember to flush the rewrite rules after you're done with step 1 above! Just visit the Permalink Settings page without having to click on the Save Changes button.
Also, if you need to support pagination (e.g. products/imports/filters/page/2
), then you'd need to adjust the above rewrite rule RegEx pattern and query for that.
本文标签: url rewritingHow to add custom rewrite rules and point to specific templates
版权声明:本文标题:url rewriting - How to add custom rewrite rules and point to specific templates 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741511852a2382651.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论