I want to add a rule to my .htaccess file that doesn't follow the Wordpress default rules.
Everything like this:
1- /course/(:any)
Must be redirected to this:
2- /course/?slug=$1
But I want to keep the URL in 1, without the query string.
Everything I try either gives me an internal server error or doesn't match the rule. This is what I got and is just being ignored (because the wordpress shows me a 'page not found' message). The resulting URL is like http://localhost/bethmoda/courses/?slug without the parameter and changing the URL
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)/course/(.*)$ /bethmoda/course?slug=$2 [L]
RewriteBase /bethmoda/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /bethmoda/index.php [L]
</IfModule>
# END WordPress
How can I do this?
You can use the following rule :
RewriteEngine On
#Exclude /bethmoda/course/index.php
RewriteCond %{REQUEST_URI} !^/bethmoda/course/index\.php$
RewriteRule ^/?bethmoda/course/(.+)$ /bethmoda/course/?slug=$1 [NC,L]
The rewriteCond is important to avoid RewriteLoop error on the second rewrite iteration, otherwise without this condition You will get an Internal server error.
The following is a wordpress way to achieve what you want.
If possbile: change "slug" with something else, lets say "course-slug".
//Add query variable, so that wordpress identifies your custom query string
function add_custom_query_var( $qvars ) {
$qvars[] = 'course-slug';
return $qvars;
}
add_filter('query_vars', 'add_custom_query_var');
Add your custom rewrite rules
//Assumption: course is a page
add_filter( 'rewrite_rules_array', 'custom_rewrite_rules' );
function custom_rewrite_rules( $rewrite_rules )
{
$pattern = "course/([^/]+)?$";
$target = "index.php?" . "name=course&course-slug=\$matches[1]";
// If course was a custom post type
// $target = "index.php?" . "post_type=course&course-slug=\$matches[1]";
// If course was a category
// $target = "index.php?" . "category_name=course&course-slug=\$matches[1]";
// If course was a tag
// $target = "index.php?" . "tag=course&course-slug=\$matches[1]";
$newRules[$pattern] = $target;
return array_merge($newRules,$rewrite_rules);
}
Flush permalink
Step 1: In the main menu find "Settings > Permalinks".
Step 2: Scroll down if needed and click "Save Changes".
Step 3: Rewrite rules and permalinks are flushed.
Related
I know this can be done using Rewrite engine but I am unable to do this
This is my .htaccess file
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I have this url www.mysite.com/report?page=my-report-name
Now what I want to acheive is this : www.mysite.com/report/my-report-name
The file where I am accessing this get variable name page is reports.php and its not in my root directory
Path to my file is : root/themes/fount/intel/reports.php
Can anyone help?
Try this code,
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
# /anything/anything -> anything.php?url=anything
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9_])/([^/]*)$ /$1.php?url=$2 [L]
</IfModule>
If the page.php filename will always be the same, then do it like this:
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
# /page/anything -> page.php?url=anything
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^page/([^/]*)$ /page.php?url=$1 [L]
</IfModule>
Thanks!
Updated answer
To add a routing which points to an external handler PHP file, the following snippet should be used:
function wprre_add_rewrite_rules() {
global $wp_rewrite;
// pattern with regexps
$wp_rewrite->add_external_rule( '^wp_report/([\w\d-]+)/?', PATH_TO_THE_EXTERNAL_HANDLER.'report.php?report_name=$1' );
}
add_action('init', 'wprre_add_rewrite_rules');
You can spot one difference in the parameter handling between add_external_rule() and the add_rewrite_rule. You must use the match selector as the Apache uses it in this case.
This snippet must placed in a file which is always loaded by your plugin or theme. If you write a plugin it can be the main plugin file. In case of theme development it can be the main functions.php file.
The custom GET parameter registration is working as it was mentioned in the Original answer.
IMPORTANT
After you edited the rewrite rules via code (external or internal both) you must go to the Permalink settings page in the admin panel and click to the Save button without any changes. This is necessary, because this will flush the rewrite rules and the WP will write into the .htaccess file the rules.
This is the reason why I recommend you to hook on the plugin activation event and register the rewrite rules then and immediately run a flush_rewrite_rules() command.
NOTES
The problem with the original answer was that, the add_rewrite_rule() function only works if you route to the default basic index.php. You can only modify the parameters, but you can not route to an external file.
Original answer
I think you should use the WordPress API to achieve this. You will need to add a rewrite rule and tag in you theme or plugin with this syntax:
!! Disclaimer this is only working to route to the basic index.php !!
For the routing, add a rewrite rule which points to your PHP file.
function custom_rewrite_basic() {
add_rewrite_rule('^report/([\w-]+)/?', 'index.php?page=$matches[1]', 'top');
}
add_action('init', 'custom_rewrite_basic');
If you want to use a query parameter which is not in the standard WP parameter list, you need to add that custom parameter name.
function custom_rewrite_tag() {
add_rewrite_tag('%page%', '([^&]+)');
}
add_action('init', 'custom_rewrite_tag', 10, 0);
Be aware to you use built in parameters if you do not use as the WP API.
In this Codex article you find more details about the topic:
https://codex.wordpress.org/Rewrite_API/add_rewrite_rule
For troubleshooting and deeper dive understanding you might to check this Codex article too, which describes the proper rewrite rule usage. Because some in circumstances you need to reset the rewrite rules (plugin activation / deactivation).
https://codex.wordpress.org/Function_Reference/flush_rewrite_rules
Finally this solution worked for me
I have added this in my functions.php file that is in our theme folder
function rewrite_photo_url(){
add_rewrite_rule('^report/([^/]*)/?','index.php?page_id=2671&value=$matches[1]','top');
}
function register_custom_query_vars($query_vars){
$query_vars[] = 'value';
return $query_vars;
}
add_action('init','rewrite_photo_url');
add_filter('query_vars','register_custom_query_vars');
and then in my php file I use get_query_var('vale') to get my parameter value
My .htaccess file
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Im getting redirect to HomePage but only on one wordPress category. Problematic category is airlines.
url/airlines/test/
Had this line previously in .htaccess, but deleted.
#RewriteRule ^airlines/(.*)/(.*).png$ ./upload-router.php?folder=$1&airline=$2 [L]
Also rebuilder permaLinks.
I can fix this bug by changing /%category%/%postname%/
to /%category%xxx/%postname%/, but ofcourse I need how it was original.
I can also FIX it by renaming category to airlines2
It might be simpler to use wp_redirect() to redirect the category.
function redirect_airlines_category() {
if (is_category( 'airlines' ) && !is_single()) {
$new_url = "http://frontpage";
wp_redirect($new_url, 301);
exit;
}
}
add_action('template_redirect', 'redirect_airlines_category');
Place this in your functions.php, change frontpage to the url of your front page, and queries to the category page should get redirected.
Fixed. Large project and somehow there was conflict between slugs. Sorry for inconvenience.
Try to update the permalink setup after updating the .htaccess file, it should fix your issue.
I have a custom URL like this:
website.com/show/?id=9999&n=page-name
I'm trying to come up with a rewrite rule to convert it to:
website.com/show/9999/page-name/
Note that this is a WordPress site and /show/ is WP page name.
Here's the rules I'm using in .htaccess:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^show/(.*)$ /show/?id=$1 [R=301,NC,QSA]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
This is working; it rewrites website.com/show/?id=9999 to website.com/show/9999/.
Then I modified the rule for the second query string:
RewriteRule ^show/(.*)/(.*)$ /show/?id=$1&n=$2 [R=301,NC,QSA]
But now website.com/show/9999/page-name/ returns a 404 error. It works if I go to: website.com/show/9999/?n=page-name.
What am I doing wrong?
Update
The 404 problem is now solved.
However, now I need to redirect the old query string URL:
website.com/show/?id=9999&n=page-name
to the new SEO friendly URL:
website.com/show/9999/page-name
How do I setup that redirect?
Try this:
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteRule ^show/(\d+)/?([^/]*)/?$ /show/?id=$1&n=$2 [L,NC,QSA]
# Wordpress defaults:
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
## Results
# show/9999 => show/?id=9999&n=
# show/9999/ => show/?id=9999&n=
# show/9999/page-name => show/?id=9999&n=page-name
# show/9999/page-name/ => show/?id=9999&n=page-name
As you see, when page-name is not available, there will be an empty n query string parameter. In your PHP script, instead of checking for the parameter presence using isset(), try using empty().
One last note; The above rules do not redirect the request, it maps the request under the hood, so that the URL stays clean. If you need a redirect, just add a R flag.
404
Even if you remove your custom rewrite rules, you'll get a 404 from WordPress. That's because, as you said, the rewrite target (/show) is a WordPress page and ultimately get mapped to the index.php file. Then, WordPress checks its database to see if it can find a page with that path or throws a 404 if it can't. Obviously, the latter is your case.
Update
Regarding your recent update; To redirect the old URL to the new one, you need some rewrite rules along the lines of:
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{QUERY_STRING} ^id=(\d+)(&n=)?(.*)$
RewriteRule ^show/?$ /show/%1/%3 [R=301,QSD,L]
# Wordpress default rules:
# ...
</IfModule>
## Results
# show?id=9999 => show/9999
# show?id=9999&n=page-name => show/9999/page-name
# show/?id=9999&n=page-name => show/9999/page-name
Don't use [R=301] until you're 100% sure that everything's working fine, as it's aggressively get cached by the browser.
I think I figured it out... almost.
#sepehr is correct that WordPress is checking, not finding the page, and throwing a 404. So I needed to use WordPress' own rewrite engine to define the rewrite rules so it recognizes what I'm doing.
So I added this to my WordPress theme's functions.php file:
add_action( 'init', 'init_custom_rewrite' );
function init_custom_rewrite() {
add_rewrite_rule(
'^show/([^/]*)/([^/]*)/?',
'index.php?page_id=2382&id=$matches[1]&n=$matches[2]',
'top'
);
}
add_filter('query_vars', 'my_query_vars', 10, 1);
function my_query_vars($vars) {
$vars[] = 'id';
$vars[] = 'n';
return $vars;
}
Now the URL website.com/show/9999/page-name works correctly, not throwing a 404.
However, now I need to redirect the old query string URL to this new one. See my updated question.
Update
Here's the rewrite rule to redirect the old query string URLs to the new SEO friendly URLs:
RewriteCond %{QUERY_STRING} ^id=([^/]*)&n=([^/]*)$
RewriteRule ^show/?$ /show\/%1\/%2\/? [R=301,L]
Please check below rule in to your .htaccess.
RewriteRule ^show/(.+)/(.+)$ show/?id=$1&n=$2 [L,QSA]
Motive: I am building my own simple cms. But when doing htaccess for my posts I am stuck when I want to add text after the id passing in url.
What i have tried so far is:
RewriteRule ^blog/(.+)$ post.php?id=$1
The problem is that when I type in http://example.com/blog/1 I get the post returned. but when I go to http://example.com/blog/1/hello-world its not working.
I want the text hello-world added to permalinks for SEO purpose.
In addition to writing regex in .htaccess, you could also route all of URLs to one PHP script, like Wordpress does:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Then, inside index.php you can split $_SERVER['REQUEST_URI'] to parts and process as you wish, like this:
$parts = explode("/", $_SERVER['REQUEST_URI']);
if($parts[1]==="blog")
{
$id = intval($parts[2]);
include("post.php");
die();
}
Below RewriteRule working fine for me.
RewriteRule ^blog/([0-9]+)/(.*)?$ blog_detail.php?id=$1&title=$2 [L]
Since your 'ugly' url does not use the title, you can simply match it, but ignore it. You are currently matching 1/hello-world in your first capture group, and your post.php page can obviously not handle this. Instead match the following:
RewriteRule ^blog/([^/]+)/[^/]+$ post.php?id=$1 [L]
Edit: Someone claims that this approach is inefficient. I beg to differ. You can do the following in php to redirect requests that were done using an incorrect url. It's exactly as efficient as a comparison of $_GET['title'] and $expectedtitle, then constructing the url. The difference is that you have no useless variables lying around, and the intention of this code is clear. You want to redirect the user if the url is not the expected url. That the expected title is not the actual title is a sideproduct.
$expectedtitle = getTitleById( $_GET['id'] );
$expectedurl = "{$_GET['id']}/{$expectedtitle}";
if( $_SERVER['REQUEST_URI'] != $expectedurl ) {
header( $expectedurl, TRUE, 301 );
}
I'm using wordpress pretty permalinks, my .htaccess file looks like this:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /nafham/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /nafham/index.php [L]
</IfModule>
# END WordPress
I'm using a form that displays the index page with url variables, like this:
http://www.nafham.com/?edu_year_selectionreal=79&semester_selectionreal=15&subject_selectionreal=80
I'd like to have the url to be displayed like this:
http://www.nafham.com/79/15/80
Is it possible to do so? and what's the best way of doing this in order not to make things go wrong with the rewrite conditions wordpress is Already applying?
as you have the rewrite already setup all you need to do is parse the url in your index.php
if (preg_match("#(\d+)/(\d+)/(\d+)#", $_SERVER['REQUEST_URI'], $regs)) {
$edu_year_selection_real = $regs[1]
$semester_selectionreal = $regs[2];
$subject_selectionreal = $regs[3];
}
add smth. like this to .htaccess:
RewriteRule ^/([0-9-]+)/([0-9-]+)/([0-9-]+)$ index.php?var1=$1&var2=($2)&var3=($3) [L]
At you need to set custom rewrite rules in the Wordpress otherwise Wordpress throw you to error page.
Here's example to set custom rewrite rules:
<?php
add_filter('rewrite_rules_array', 'insert_custom_rules');
function insert_custom_rules($rules)
{
$newrules = array();
$newrules['(.+?)/(.+?)/(.+?)/?$'] =
'index.php?edu_year_selectionreal=$matches[1]&semester_selectionreal=$matches[2]&subject_selectionreal=$matches[3]';
return $newrules + $rules;
}
?>
Hope this will help.