I'm having a strange issue trying to add a rewrite rule.
Firstly, a note about my set-up. I'm using a date.php file for another specific set-up on the site.
The area I'm having issues with is a customized Archives page.
In order to not mess with the date.php template I attempted to set up a new page within wordpress and then created my own template to display the archives.
In order to catch the url with the date and not redirect to the date.php I set up the following add_rewrite_rules :
function my_archives() {
add_rewrite_rule("my-archives/([0-9]{4})/([0-9]{1,2})/page/([0-9]{1,})/?$", 'index.php?pagename=my-archives&year=$matches[1]&monthnum=$matches[2]&paged=$matches[3]', 'top');
add_rewrite_rule("my-archives/([0-9]{4})/([0-9]{1,2})/?$", 'index.php?pagename=my-archives&year=$matches[1]&monthnum=$matches[2]', 'top');
}
add_action('init', 'my_archives');
I thought everything was a-ok as my links were working correctly.
Example:
http://mysite.com/my-archives/2013/09/
as well as
http://mysite.com/my-archives/2013/09/page/2/
for paged results.
Now a month later I see that for some reason it'll only correctly redirect to dates that are one month behind the current date.
So being that the current date is 2013/10/ it's only redirecting /2013/09/ and everything else is being redirected to the 404 page.
Any suggestions on probable cause for this or if someone sees something in my code that is incorrect it'd be greatly appreciated.
Are you by any chance simply not having any results for that query?
Are you hooking to the WordPress query in order to make sure that WordPress understands the query correctly(it's possible that WordPress is trying to find a page with slug "my-archives" within the specified year and month - and when it can't it shows a 404 error).
Try doing the following:
var_dump( get_posts( 'pagename=my-archives&year=2013&monthnum=10' ) );
and see if that returns any results. If it doesn't - then that's most-likely your issue.
To work-around that, I would advise that you change your rewrite rules to something like:
add_rewrite_rule("my-archives/([0-9]{4})/([0-9]{1,2})/?$", 'index.php?pagename=my-archives&my_year=$matches[1]&my_monthnum=$matches[2]', 'top');
Since I assume that if you're not hooking to the main WordPress query, you are executing the query on your custom page template. There you should look for the my_year and my_monthnum query variables instead of year and month.
Keep in mind, that actually modifying the main WordPress query(on the either parse_request(passes the $wp object and not $wp_query) or the pre_get_posts action(passes the $wp_query object) ) might be a better solution.
Related
I build a Wordpress website with a page called 'Nieuwsberichten'.
The url looks like
https://www.example.com/nieuwsberichten
This page is dynamic and I need an extra parameter called 'news_page'
https://www.example.com/nieuwsberichten/?news_page=recent
The URL above is not friendly so I create a rewrite rule for this and I add the variable 'news_page'.
functions.php
function add_query_vars($vars){
$vars[] = 'news_page';
return $vars;
}
add_filter( 'query_vars', 'add_query_vars', 10, 1 );
function rewrite_paged(){
add_rewrite_rule('^nieuwsberichten/([0-9]+)/?', 'nieuwsberichten?news_page=$matches[1]', 'top');
}
add_action('init', 'rewrite_paged');
After this I flushed the permalinks
menu -> settings -> permalinks -> save
If I browse to
https://www.example.com/nieuwsberichten/recent/
It will redirect to
https://www.example.com/nieuwsberichten/
What do I miss in my code?
Hope somebody can help me with this
In the regex part, you specify an entry for numbers only, but you pass text like recent in your url. Maybe the error is here. Please check if it works with number input, edit your expression if that's the problem. Also, the url structure you specified does not seem to be quite correct.
Anyway, I'm not sure of my answer so I'd appreciate it if you could confirm after checking.
https://developer.wordpress.org/reference/functions/add_rewrite_tag/
This may be the function you should use for the parameters you add. This function will also not require the query_var function. So I think you won't need to use the other function.
I'm not in a position to check or test right now. If your problem is not solved, I will look into it in detail.
You can use it like this:
function rewrite_paged(){
add_rewrite_tag('%news_page%', '([^/]+)');
add_rewrite_rule('^nieuwsberichten/?([^/]*)$', 'nieuwsberichten?news_page=$matches[1]', 'top');
}
add_action('init', 'rewrite_paged');
Also if you are pointing to a page you will need to use page id or pagename. A blog or a product etc. If it is, there will still be parameters you need to use and you should redirect this url to index.php. I'm leaving an example for you to understand what I'm saying, and for your review, you can take a look at the rewrites on your site as follows:
Review examples:
global $wp_rewrite;
print_r($wp_rewrite);
Examples:
Match Pagename:
add_rewrite_rule('^nieuwsberichten/?([^/]*)$', 'index.php?pagename=nieuwsberichten&news_page=$matches[1]', 'top');
Match Page ID:
add_rewrite_rule('^nieuwsberichten/?([^/]*)$', 'index.php?page_id=10000&news_page=$matches[1]', 'top');
If you have an installation outside of wordpress your example is correct but if it will be inside wordpress all requests should be directed to index.php. Therefore, you may need to edit the code I have given like these examples.
Hello Everyone and thank you for your help!
I have an external (outside wordpress in root directory) php file that I would like to use the custom_rewrite_rule function to make the url pretty as well as pass on information for variables that will look up an API record from that URL. You might ask why I haven't done it the regular way and made it a page template inside wordpress, and that is because I am using a custom JQuery slideshow that seems to have trouble running inside a wordpress environment.
So what I have in my child themes functions.php is:
function custom_rewrite_rule() {
add_rewrite_rule('^yacht-details/([^/]*)/([^/]*)/?','yacht-details.php?info=$matches[1]&boatid=$matches[2]','top');}
add_action('init', 'custom_rewrite_rule', 10, 0);
and in the php file am using the standard $_GET to acquire the information.
$info = $_GET["info"];
$boatid = $_GET["boatid"];
My actual problem is what I am actually getting is literally $matches[1] and $matches[2] instead of the variables.
What am I doing wrong? Does this need to be done with .htaccess instead of functions.php? The problem I run in to going that route is wordpress does not seem to like more than one subfolder.
Thank you again.
I have a page called 'all-products' on Wordpress, and I want to get products using id in the url as domain.com/all-products/4382zcxs2133
function add_my_var($public_query_vars) {
$public_query_vars[] = 'routeparam';
return $public_query_vars;
}
add_filter('query_vars', 'add_my_var');
function do_rewrite() {
add_rewrite_rule('all-products/[a-zA-Z0-9]/?$', 'index.php?pagename=all-products&routeparam=$matches[1]','top');
}
add_action('init', 'do_rewrite');
Then, when I tried using $wp_query->query_vars['routeparam'], it says 'undefined index'.
When I var_dump($wp_query->query_vars), I can actually see the value in an index called page but that only works for numbers. If I use letters and numbers instead, I get 404 error.
Edit:
/all-products/213213 - works
/all-products/ - works
/all-products/21321dsa3fsa - doesn't work
I tried the regex on a fiddle, it works, but on Wordpress in add_rewrite_rule, it doesn't work. Here is the fiddle
Edit 2:
I've commented out my write rule line, and it looks like it can still access product/123 so somehow, my rewrite rule is not registering.
I tried var_dump($wp_rewrite) and I can confirm that my rewrite rule is registered but I believe that default wordpress pagination ('pagination_base' exactly) may cause this.
Because when I comment out add write rule and visit the url through /all-products/123, I can still access the page without a 404 and I can see that '123' value I have provided is shown as 'page' in $wp_query->query_vars.
You can use
'products(?:/([a-zA-Z0-9]+))?/?$'
or if this part is always at the beginning, add ^:
'^products(?:/([a-zA-Z0-9]+))?/?$'
Note the + and (...) parentheses around [a-zA-Z0-9]+ that form Group 1 and its value will be used via $matches[1].
And Do not forget to flush and regenerate the rewrite rules database after modifying rules. From WordPress Administration Screens, Select Settings -> Permalinks and just click Save Changes without any changes..
I've been looking for hours trying to find a straightforward answer to this but I just can't seem to find anything out there which tackles this issue. There are numerous examples for rewriting standard URLs, but nothing in-terms of rewriting pages from within a custom plugin.
I've created a custom plugin with a special directory in it called test. The test directory has several pages which are blah.php and shmeh.php. Is it possible to create rewrite rules to these pages i.e. http://example.com/blah, http://example.com/shmeh
Thank you very much for all the help.
So essentially what you are looking for, is to have Wordpress load a specific page template (blah.php) when the user visits http://example.com/blah/. Also, you need it to to be completely generated in your plug-in without actually creating any pages or posts. You are on the right track. What you want to do here is create a rewrite rule that utilizes a specific query var to load the page. Here it is step by step:
Step 1: Rewrite rules
http://codex.wordpress.org/Function_Reference/add_action
http://codex.wordpress.org/Plugin_API/Action_Reference/init
http://codex.wordpress.org/Rewrite_API/add_rewrite_rule
/* Rewrite Rules */
add_action('init', 'yourpluginname_rewrite_rules');
function yourpluginname_rewrite_rules() {
add_rewrite_rule( 'blah/?$', 'index.php?blah=true', 'top' );
}
So in the above code, your just telling Wordpress that example.com/blah/ should be treated as if the user were visiting example.com/index.php?blah=true. Now "blah" is a query var that you will set up in the next function below. Query vars are just what Wordpress calls $_GET variables. However they must be registered with Wordpress so it can properly store the value (which is "true" in this case). We will do that below in the next function. It's also worth noting the third setting in the function "top", which gives this rewrite rule priority over other rewrite rules. Alternatively, setting it to "bottom" would check that no other rewrite rules match first before using this one.
Step 2: Query Vars
http://codex.wordpress.org/Function_Reference/add_filter
http://codex.wordpress.org/Plugin_API/Filter_Reference/query_vars
/* Query Vars */
add_filter( 'query_vars', 'yourpluginname_register_query_var' );
function yourpluginname_register_query_var( $vars ) {
$vars[] = 'blah';
return $vars;
}
In the code above, your just registering the query var "blah" with Wordpress. That way, when someone visits example.com/blah/, which your rewrite rule tells Wordpress to treat it like they are visiting example.com/index.php?blah=true, Wordpress actually bothers to save it's value (which is set to true). This is so you can use it in the next function, which loads the template you want when users visit your url.
Step 3: Template Include
http://codex.wordpress.org/Function_Reference/add_filter
http://codex.wordpress.org/Plugin_API/Filter_Reference/template_include
http://codex.wordpress.org/Class_Reference/WP_Query#Interacting_with_WP_Query
http://codex.wordpress.org/Function_Reference/plugin_dir_path
/* Template Include */
add_filter('template_include', 'yourpluginname_blah_template_include', 1, 1);
function yourpluginname_blah_template_include($template)
{
global $wp_query; //Load $wp_query object
$page_value = $wp_query->query_vars['blah']; //Check for query var "blah"
if ($page_value && $page_value == "true") { //Verify "blah" exists and value is "true".
return plugin_dir_path(__FILE__).'test/blah.php'; //Load your template or file
}
return $template; //Load normal template when $page_value != "true" as a fallback
}
In the code above, you are simply telling Wordpress to use your blah.php template any time the query var "blah" is present and set to true. In this case it is present because a user is visiting a url with a rewrite rule that utilizes the "blah" query var. The function checks if the "blah" query var is present, then checks if "blah" is set to true, and if so loads the template. Also note that the template path is test/blah.php. You are using plugin_dir_path(__FILE__) to relatively include the template based on the location of your plugin. That way it's relative as a plug-in should be.
Step 4: The Actual Template (blah.php)
http://codex.wordpress.org/Function_Reference/get_header
http://codex.wordpress.org/Function_Reference/get_footer
http://codex.wordpress.org/Function_Reference/get_sidebar
Your template file will need to load the header, footer, and sidebar itself. When using template_include, Wordpress will not automatically load the header and footer as if you were using a page template. Be sure your template file calls get_header(), get_footer(), and get_sidebar() so that you get your complete layout.
Notes
Hope this helps, I was searching for something similar the other day and had to figure it out the hard way. It's also worth noting that I have prefixed all of the functions as "yourpluginname_". You can change this to whatever you want your prefix to be, but be sure to update the function names to match as well.
I have links in my site that pass queries to pages that query from an external database. This works fine e.g.
mysite.com/catalog/?tl=flooring
however i want to rewrite this url to appear as
mysite.com/catalog/flooring
Ive tried modifying the rewrite rules in wordpress but it always displays the index page
add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');
// Remember to flush_rules() when adding rules
function flushRules(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
// Adding a new rule
function wp_insertMyRewriteRules($rules)
{
$newrules = array();
$newrules['(catalog)/([a-zA-Z0-9 ]+)$'] = '/catalog/?tl=$matches[2]';
return $newrules + $rules;
}
// Adding the id var so that WP recognizes it
function wp_insertMyRewriteQueryVars($vars)
{
array_push($vars, 'id');
return $vars;
}
Rewrite rules in WordPress don't quite work like how you're expecting them to. All rewrite rules map to a file handler (almost always index.php), not another URL.
Here is a shortened code example;
$rules['catalog/(.*)/?'] = 'index.php?pagename=catalog&tl=$matches[1]';
array_push($query_vars, 'tl'); // note query var should match your query string
This would map catalog/whatever to the WordPress page 'catalog', and pass along the query var 'tl'. You could create a page template for 'catalog', then pick up the value of 'tl' using get_query_var('tl').
Also avoid using query vars like id - use something more unique (like 'tl') to avoid clashes with WordPress.
And don't flush rules on every init! It's bad practice, and will write to .htaccess and call database updates on every page load!
WordPress will always flush permalinks whenever you update a post or your permalink structure (simply update your permalinks when you make changes to your code).
This article over at Raazorlight goes into a bit more detail on the process of grabbing querystrings and URL rewriting in WP.
Also, check the comments there to see why calling flushRules() may not be necessary if you re-save permalinks. Optionally, flushRules() can be called just once during plugin activation callback.
Digging deeper, commenter 'pmdci' links over to an instructive post/saga on the related topic of passing a query to a custom post type using a custom taxonomy.