Reputation: 1071
I have read a ton and tried a ton of solutions, but can't find one specific to my needs.
In my htaccess I have the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^profile/([\w-]+)/?$ profile.php?username=$1 [L,QSA]
RewriteRule ^profile/([\w-]+)/([\w-]+)/?$ profile.php?username=$1&type=$2 [L,QSA]
RewriteRule ^profile/([\w-]+)/([\w-]+)/([\w-]+)/?$ profile.php?username=$1&type=$2&o=$3 [L,QSA]
This works wonderfully, except for 1 small problem.
If profile/username
does not have a /
the links on the page will break unless absolute urls are used. So <a href="./1">
will end up as profile/1
instead of profile/username/1
If I change the first rewrite to the following:
RewriteRule ^profile/([\w-]+)/$ profile.php?username=$1 [L,QSA]
then https://myurl/username
will return a 404 which I do not want - I want it to force the / on the end if it does not exist.
I have tried adding:
RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301]
I have tried
RewriteRule ^(.*)$ https://nmyurl/$1/ [L,R=301]
Just can't figure out how to do this with the rewrite conditions already in place.
Upvotes: 1
Views: 439
Reputation: 1071
So unfortunately I wasn't able to actually achieve what I was hoping to because there are multiple levels of variables that may or may not exist.
In part I used the solution provided by Amit:
RewriteCond %{REQUEST_URI} ^/profile/
RewriteRule !/$ %{REQUEST_URI}/ [L,R]
However this wasn't enough, because as pointed out by MrWhite there are 3 separate potential url's.
https://myurl/profile/username/
https://myurl/profile/username/type/
https://myurl/profile/username/type/o/
In this sitation username should always exist, but type and o may or may not exist.
So what I did was detect the level of the url and then created conditional . and .. using php.
The variable o is always numeric and variable type is never numeric so this worked for me.
if (isset($_GET['o'])) { $o = strip_tags($_GET['o']); }
elseif (isset($_GET['type']) && is_numeric($_GET['type'])) { $o = strip_tags($_GET['type']); }
Then I detect:
// if o is set or if type is numberic, use ..
if (isset($_GET['o']) || (isset($_GET['type']) && is_numeric($_GET['type']))) {
$dots = '..';
// if o is not set and type is not numeric just use .
} else {
$dots = '.';
}
end result of <a href="'.$dots.'/1/">1</a>
:
if url is https://myurl/profile/username/
result is https://myurl/profile/username/1/
if url is https://myurl/profile/username/3/
result is https://myurl/profile/username/1/
if url is https://myurl/profile/username/type/3/
result is https://myurl/profile/username/type/1/
Which was the desired outcome.
Upvotes: 0
Reputation: 45914
If
profile/username
does not have a/
the links on the page will break unless absolute urls are used. So<a href="./1">
will end up asprofile/1
instead ofprofile/username/1
If the issue only applies to URLs of the form /profile/<username>
then I would be specific and only append the trailing slash to these specific URLs, otherwise, you are going to get a lot of redirects (which could be detrimental to SEO).
However, you should ensure that internal links are for the canonical URL (ie. with the trailing slash).
For example, the following should go before your existing rewrites:
RewriteRule ^(profile/[\w-]+)$ /$1/ [R=301,L]
Since the canonical URL requires a trailing slash this should be a 301 (permanent) redirect. (But test with a 302 first.)
Alternatively, instead of redirecting in .htaccess
(if you are still linking to the slashless URL internally) then you could add a base
element (that includes the trailing slash) to the head
section to state what relative URLs should be relative to.
For example:
<base href="/profile/<username>/">
Aside:
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^profile/([\w-]+)/?$ profile.php?username=$1 [L,QSA] RewriteRule ^profile/([\w-]+)/([\w-]+)/?$ profile.php?username=$1&type=$2 [L,QSA] RewriteRule ^profile/([\w-]+)/([\w-]+)/([\w-]+)/?$ profile.php?username=$1&type=$2&o=$3 [L,QSA]
The two RewriteCond
directives would seem to be entirely superfluous. RewriteCond
directives only apply to the first RewriteRule
that follows. But the RewriteRule
patterns are unlikely to match real files anyway (unless you have files without extensions or directories with the same name).
Upvotes: 1
Reputation: 41229
To add an optional traling at the end of your profile
URLs you can use this
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/profile/
RewriteRule !/$ %{REQUEST_URI}/ [L,R]
Upvotes: 1