add_rewrite_rule not working when referencing child page name as matches - wordpress

Is anyone able to comment why this does not work.
I have created a custom post type called "knowledge-hub". I also then created a page called "knowledge-hub" to act as the landing page for my CPT listings, which I show using code. On one of the CPT pages, "minimum-wage-policies", I want to be able to access a variable in the URL, e.g. ?some_var=xyz. But I want it friendly like /knowledge-hub/minimum-wage-policies/xyz.
So I have created rewrite URLs. The page name "minimum-wage-policies" will vary for many of the CPT pages, so I cant hard code this. I want to access it using a URL part.
But I cant get the add_rewrite_rule() to match matches[1] to the page name. If I hard code this page name in the add_rewrite_rule it works! But as soon as I replace it with matches[1] it does not work, its either a 404 or a redirect back to minimum-wage-policies with no variable on the end.
URL would be:
http://my-domain.com/knowledge-hub/minimum-wage-policies/some_var
Referencing the child page name works:
add_rewrite_rule(
'knowledge-hub/([^/]*)?/([^/]*)/?$',
'index.php?post_type=knowledge-hub&pagename=minimum-wage-policies&my_var=$matches[2]',
'top'
);
matches[2] is working in this case as I can see the value passed in the URL in my code.
But using matches[1] does not work and returns a 404:
add_rewrite_rule(
'knowledge-hub/([^/]*)?/([^/]*)/?$',
'index.php?post_type=knowledge-hub&pagename=$matches[1]&my_var=$matches[2]',
'top'
);
Visiting the WP URL http://my-domain.com/index.php?post_type=knowledge-hub&pagename=minimum-wage-policies&my_var=xyz works, so that structure is OK.
I have tried various regex expressions used by various others on the internet, so not just ([^/])?. So am not sure if it is to do with the regex and I just have not found the right one. I want to match anything. Same issue with (.)
I also have this:
function add_my_vars($vars)
{
$vars[] = 'my_var';
return $vars;
}
add_filter('query_vars', 'add_my_vars');
Update:
Using $request->matched_query I could see the URLs being called.
When I use pagename=minimum-wage-policies the URL is as expected:
post_type=knowledge-hub&pagename=minimum-wage-policies&my_var=xyz
When I use matches[1] is completely changed which is quite bizarre:
knowledge-hub=minimum-wage-policies%2Fxyz&page=

I managed to get it working with this rewrite_rule but I have not found this structure online so not sure if its technically correct but it works. Note the use of knowledge-hub=$matches[1]. This was discovered from viewing the $request->matched_query I mentioned was bizarre above. Replicating it in the rewrite_rule makes it work.
add_rewrite_rule(
'knowledge-hub/([^/]*)?/([^/]*)/?$',
'index.php?knowledge-hub=$matches[1]&my_var=$matches[2]',
'top'
);

Related

Home page url rewriting Wordpress

I want to do a URL rewrite in the WordPress home page
I want to change my URL http://mysite.loc/?pays=senegal to look like http://mysite.loc/senegal.
The problem is that I am on the WordPress home page, so it will be confused with the URL of another page like http://transfert.loc/page-example.
I have already tried several optins but am completely blocked.
Here is my code example:
public function rewrite_urls(){
add_rewrite_tag( '%pays%','([^&]+)' );
add_rewrite_rule(
'([^/]+)',
'index.php?pays=$matches[1]',
'top'
);
}
Can someone help me please!
Thanks
Two problems I see- rewrite rules need to set query vars that will result in a successful main query. Setting just a custom var like slide doesn't parse to anything WordPress can load. Additionally, slide needs to be added to the recognized query vars for it to get parsed within a rule.
So, what would a rule look like that would load the front page posts in the main query? That's a good question- the posts page is a special case, the absence of any other query vars. I haven't found a way to do that with a rule, though it may exist.
An easier way to do this is with a rewrite endpoint:
function wpd_endpoint(){
add_rewrite_endpoint( 'page-example', EP_ROOT );
}
add_action( 'init', 'wpd_endpoint' );
Keep in mind that if you have code accessing values via $_GET, this still won't work, because WordPress doesn't put query vars there when rules are parsed. You can change the code to use get_query_var, or just assign it before the code tries to access it:
$_GET['page-example'] = get_query_var('page-example');

Wordpress Url Rewrite with Multiple Parameters and Templates - Dynamic Path/Parameter Placement

We're having some trouble figuring out WP URL rewrite rules when we have tokens separated by parameters. Very briefly, we'd like to have the following common format for user pages and video libraries:
/users/steve/videos/2
...where "users" is the PHP page template that displays details on a user. So if we go to:
/users/steve/
...we see Steve's home page. If we go to:
/users/steve/videos/
...we hit the page template for the video library, and we see Steve's list of videos. And if we go to:
/users/steve/videos/2
...we hit a third page template, the video player page, where we see video id 2 displayed.
So we have three separate page templates, and we would like the child / parent relationship between them to be user page -> video library page -> video player page, for our breadcrumbs display.
The trick we can't figure out is that "steve" and "2" are really params inserted into the url, interrupting the parent/child token relationship. And second, for the video player, there really isn't a token there at all that maps to the video player page template. It's just the presence of the "videos" token plus the additional numerical parameter that tells us this maps to the video player page template.
As alternative, we've figured out how to get /users/videos/steve/2 working. We've added this rewrite rule to our child theme's functions.php file:
add_rewrite_rule(
'^users/videos/([^/]*)/([^/]*)/?',
'index.php?pagename=users/videos&users_filter_name=$matches[1]&user_video_id=$matches[2]',
'top');
(we've also defined the variables "users_filter_name" and "user_video_id" and we are successfully parsing them in the template)
But since what we really would like is /users/steve/videos/2 we tried updating the rule to:
add_rewrite_rule(
'^users/([^/]*)/videos/([^/]*)/?',
'index.php?pagename=users/videos&users_filter_name=$matches[1]&user_video_id=$matches[2]',
'top');
That didn't seem to work (it just loaded the '/users/' page) so we're obviously doing it incorrectly. Is what we want achievable with this structure?
Thanks!
The link structure of /users/steve/videos/2/ format is not a problem for Wordpress, and you actually wrote all the right code, but there is a small mistake somewhere.
Most likely you have a problem in the code section where you add new variables to query_vars.
Perhaps you are adding a second variable in too late action.
When Wordpress sees an obscure variable, it often behaves as you described.
Try removing all of your code and copy this to functions.php top
add_rewrite_rule(
'^users/([^/]*)/videos/([^/]*)/?',
'index.php?pagename=users/videos&users_filter_name=$matches[1]&user_video_id=$matches[2]',
'top');
add_filter( 'query_vars', function( $vars ){
$vars[] = 'users_filter_name';
$vars[] = 'user_video_id';
return $vars;
} );
If it doesn't work, try changing the code to this
add_rewrite_rule(
'^users/([^/]*)/videos/([^/]*)/?',
'index.php?page_id=54&users_filter_name=$matches[1]&user_video_id=$matches[2]',
'top');
add_filter( 'query_vars', function( $vars ){
$vars[] = 'users_filter_name';
$vars[] = 'user_video_id';
return $vars;
} );
Where 54 = your page ID
After each change you must go to the settings and turn off/on permalinks to reset the cache
I tested this code on my demo it works 100%.

Wordpress url parameter "country" on every page

I would like to use a custom URL parameter for my wordpress site, called country.
This parameter should only be used internally.
For translation I use WPML. I know that it would be possible to create a language for every country / language combination but then I would have to maintain the same language for so many countries and that would be too much effort.
Anybody got an idea how I can make the url look something like that?
www.my-domain.com/de/at -> front page
www.my-domain.com/de/at/my-post -> other page
add_action('init', 'rewritecustom');
function rewritecustom(){
add_rewrite_tag('%country%', '([^&]+)', 'country=');
add_rewrite_tag('%lang%', '([^&]+)', 'lang=');
add_rewrite_rule(
'^([a-z]{2})\/([a-z]{2})\/([^\/]*)',
'index.php?pagename=$matches[3]&country=$matches[2]&lang=$matches[1]',
'top'
);
}
In the permalink settings I set the url to
https://www.my-domain.com/%lang%/%country%/%postname%/
But unfortunately I get a 404 error when I try this.
Anybody got an idea how to solve it?

WordPress: add_rewrite_rule with flexible path length? (Tag filter)

I need your help regarding WordPress URL rewrite. :o) At first, I am get this working:
add_rewrite_rule( 'category/([^/]+)/([^/]+)/?(?:page/?([0-9]{1,})?/?)?$' , 'index.php?category_name=$matches[1]&tag=$matches[2]&paged=$matches[3]', 'top');
This does some actions:
I can enter "blog.domain/category/category-name/" and get to the
category archive - with or without "page(d)"
I can also enter
"blog.domain/category/category-name/a-tag/" (or with "page/n/") and
get to the category archive, where the posts are filtered by an tag.
Now, I could extend this rewrite rule, f.e.:
add_rewrite_rule( 'category/([^/]+)/([^/]+)/([^/]+)/?(?:page/?([0-9]{1,})?/?)?$' , 'index.php?category_name=$matches[1]&tag=$matches[2]+$matches[3]&paged=$matches[4]', 'top');
This one will also works with "blog.domain/category/category-name/tag1/tag2/".
What I want to do is an pretty URL, so that users could filter the posts more and more by tags (f.e. /category/cars/racing/red/). Problem: for every new "path" (for category/cars/racing/ and category/cars/racing/red/) I need one add_rewrite_rule.
Is there any solution to reach this behavior with one single line? Maybe something like "there could be another path (as tag), but it mustn't"?

Can I edit my .htaccess to write some WorldPress URL's (custom rewrites)?

So here's the problem: We don't like the fact that WordPress doesn't allow duplicate slugs, even for sub categories meaning we cannot have urls like:
product-1/guides
product-1/articles
product-2/guides
product-2/articles
That's very annoying! One solution we are considering is setting up our slugs like this:
product-1/product-1-guides
product-1/product-1-articles
product-2/product-2-guides
product-2/product-2-articles
But in our htaccess - can we use it to pick up such urls and rewrite them as prettier urls which have the product name removed from the sub folder? We don't mind hard coding these as we'll only ever have 5-10 products on the site.
This would keep the WordPress install happy with unique slugs, but the SEO tick in the box with better looking urls.
I just need a hand with the syntax please?
EDIT 1:
After looking at the WordPress Rewrite API, I'm failing to get anywhere with what I think is a really simple test. I have the following code in my functions.php which is running as I tested an echo, but no rewriting is taking place?
add_action( 'init', 'productRewrites' );
function productRewrites() {
add_rewrite_rule('^wordpress/james?','index.php?author_name=jwilson','top');
}
Nothing happens when I hit:
mysite.com/wordpress/james
Edit 2:
Cool I realise I now have to click save each time. The problem I now have is the following does not work not when I use $matches[1] - it only works if I hard code the author_name value (to jwilson for example):
function productRewrites() {
add_rewrite_rule(
"writer/([^/]+)/?",
"index.php?author_name=$matches[1]",
"top");
}
When I use $matches[1] it just returns everything! So clearly isn't using ([^/]+) in the url?!
you have to reset permalink structure
in order to do that, move to Settings -> Permalinks and press Save changes button

Resources