.htaccess mod_rewrite check if querystring var is avail - php

Basically I want to rewrite my urls so that it is website.com/folder/ sometimes though I need it to rewrite also website.com/folder/page/
Currently I have it working with just the website.com/folder/ but can not get it to check if there is a page, if I create just another rule under the folder one it reads that one, and gives me an empty page var, which is breaking my php. I struggle with .htaccess and any help would be appreciated.
Here is what I have that works with just the folder but I can not include a page.
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|docs)/
RewriteRule ^([^/]*)/$ /?folder=$1 [QSA]
Here is what I tried to get it to work with either just a folder, or a folder and page
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/$ /?folder=$1 [QSA]
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/([^/]*)/$ /?folder=$1&page=$2 [L,QSA]
Please Help!

Accordingly to the RewriteRule docs you should reverse the rules order in your rules set. Because in your configuration both rules have the same RewriteCond, the most specific rule (folder + page) should be atop and the most general rule should be the last one. If not when the first rule is matched the URL is rewritten and the second rule never matches. Also, probably you want to remove the trailing forward slash in the pattern of your folder + page rule (assuming that the second group in the pattern matches a page not a folder). So I think the whole thing should read:
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/([^/]*)$ /?folder=$1&page=$2 [L,QSA]
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/$ /?folder=$1 [L, QSA]

Related

how to make a htaccess rule from id to name

I have a list of unique data:
Suppose I have the following data:
id name
1 Jhon
2 Peter
3 Mark
4 Scotty
5 Marry
I make a .htaccess rule for id:
RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]
my URL is:
http://localhost/mate/admin/site/brandlisting/3
this works for id.
Now I need a .htaccess rule for name, so I make a rule for it:
RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L]
http://localhost/mate/admin/site/brandlisting/Mark
When I used the above URL I was faced with following error in the console:
"NetworkError: 400 Bad Request -
http://localhost/mate/admin/site/brandlisting/Mark"
and in browser it shows:
Error 400 Your request is invalid.
My current .htaccess file
RewriteEngine on
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$
RewriteCond %{REQUEST_URI} !wordpress/
RewriteRule (.*) /wordpress/$1 [L]
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]
#RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
#RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]
RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L]
I am starting with your current .htaccess you have crunch all the available rule which meets your needs in one single .htaccess for example rule for wordpress it should be in directory where your wordpress is installed.
Your rule as per your requirement should be like this if you are trying in root directory,
RewriteEngine on
RewriteBase /mate/admin/
RewriteRule site/brandlisting/([\d]+)/?$ site/brandlisting.php?id=$1 [L]
RewriteRule site/brandlisting/([a-zA-Z]+)/?$ site/brandlisting.php?name=$1 [L]
And for wordpress you directory you can create seperate .htaccess where you can put your rule index.php.
.htaccess rules rely on order. If you anticipate using a lot of routes, keep your htaccess rules simple and put your routes into PHP instead, using one of the several already written routing frameworks.
Here's an explanation as to why your .htaccess file isn't working, line-by-line:
RewriteEngine on
This turned the RewriteEngine on. No problems so far.
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$
RewriteCond %{REQUEST_URI} !wordpress/
Only match RewriteRule is it's WordPress. This seems to be working, so let's ignore this block of rules.
RewriteRule (.*) /wordpress/$1 [L]
Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Only match below if the requested filename is not a file or a directory.
RewriteRule .* index.php/$0 [PT,L]
Rewrite any path PATH to index.php/PATH. Stop processing if it matched (note the L as last). That means nothing below will be activated.
#RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
#RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]
RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L]
Assuming that it doesn't match .* (aka, never), check path for other patterns. Note also that the two lines you have commented, and the two lines you don't, both match the same pattern. If one worked, the other would not.
-- Pro Tip: Regex has a shorthand for including a rule with a trailing slash and without one: /? is equivalent to, either with one slash, or with no slashes. Another way to write this is /{0,1}.
How to Fix
.htaccess redirect rules are a pain. My rule of thumb is to make them as easy as possible to write, which makes them easy to read and to maintain. How to do this? Push the redirect logic to your PHP program, rather than forcing Apache to rely on it.
Solution 1
The htaccess-only approach here would be to ensure you understand what Apache rewrite flags are telling your server to do, and adjust accordingly. You can do this here one of two ways:
Make your more specific rules show up first. i.e., move /site/brandlisting?name=$1 rules to before .* rules.
Add a separate rewrite conditions for any followup processing. As per the Apache2 documentation linked above:
The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed. This corresponds to the last command in Perl, or the break command in C. Use this flag to indicate that the current rule should be applied immediately without considering further rules.
The key point here is that it is within each rule set. Building a new rule set will continue processing.
Example that should work (not tested):
RewriteEngine on
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$
RewriteCond %{REQUEST_URI} !wordpress/
RewriteRule (.*) /wordpress/$1 [L]
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]
#New Rule Set
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Note that /? is the same as writing two separate rules,
# one with a slash at the end, and one without.
RewriteRule brandlisting/(.*)/? site/brandlisting?name=$1 [L]
There are some great pre-built routers out there, like Silex and Slim. If you don't want to use them, you can still use your own internal logic that parses various pieces. From my experience, the more that I can pull out of my .htaccess file, the happier you'll be. It winds up being far easier to debug issues, and it's easier to iterate changes without introducing unintended consequences.
Solution 2
You can use PHP routers in conjunction with the .htaccess file I provided above, like so:
// Slim example
$app = new Slim\Slim();
$app->get('/brandlisting/:key', function ($key) {
if (is_numeric($key)) {
$id = $key;
// call/run $id logic
} else {
$name = $key;
// call/run $name logic
}
});
// ...
$app->run();
If you do this, you can remove any of your brandlisting logic from .htaccess and instead put it into your index.php.
Conclusion
If you can help it, experience tells me that it's better to not write your app logic into .htaccess rules. Instead, make your .htaccess rules simple and use a routing library. If you want to use .htaccess, make sure you understand the Apache rewrite flags you're using, and that Apache reads everything from top to bottom. For example, if the [L] flag is used, Apache stops reading all other rules in the rule set. That means, you have to create a new rule set with additional rules that need to be processed, or put your more specific rules first. Keep in mind that, if those rules have an [L] flag, they will also stop execution of any subsequent rules.
You can use redirect here.
Assuming you have the following folders:
<server root>/mate/admin
place in .htaccess in mate/admin
RewriteBase /mate/admin/
RewriteRule "site/brandlisting/([^\\]+)/" "site/brandlisting?id=$1" [R,L]
RewriteRule "site/brandlisting/([^\\]+)" "site/brandlisting?id=$1" [R,L]
You may be running into an issue where a Directory or other directive is causing your rewrite rules to repeatedly fire and cause infinite redirects.
See the documentation for RewriteRule Flags: L.
Specifically, the following quoted text is relevant:
If you are using RewriteRule in either .htaccess files or in
sections, it is important to have some understanding of
how the rules are processed. The simplified form of this is that once
the rules have been processed, the rewritten request is handed back to
the URL parsing engine to do what it may with it. It is possible that
as the rewritten request is handled, the .htaccess file or
section may be encountered again, and thus the ruleset may be run
again from the start. Most commonly this will happen if one of the
rules causes a redirect - either internal or external - causing the
request process to start over.
It is therefore important, if you are using RewriteRule directives in
one of these contexts, that you take explicit steps to avoid rules
looping, and not count solely on the [L] flag to terminate execution
of a series of rules, as shown below.
You may need to add a rewrite condition or take other steps to prevent looping.

Changing URLs when using $_get to determine webpage

I currently use $_GET['base'] to determine which homepage that the user visits.
This results in localhost/?base=administrator or localhost/?base=guest
I am also using this to control which page is the user at, such as
localhost/?base=guest&page=register
Is there any way to use mod_rewrite, or htaccess, to change how this system works?
Modifying my code is not an issue, is this possible?
EDIT:
I am trying to achive this:
localhost/?base=guest to localhost/guest
localhost/?base=admin to localhost/admin
localhost/?base=guest&page=register to localhost/guest/register
Below is my htaccess file
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)$ /?base=$1&page=$2 [L]
RewriteRule ^([^/]*)$ /?base=$1 [L]
Will the document path affect how it is being called? As I am using a case loop to include which items are needed.
This, however, works for localhost, but it will loop every other address to main.
RewriteEngine On
RewriteRule ^$ /index.php?base=guest[L]
But did not give a result as expected.
Your rules in .htaccess need to be in reverse order, like below:
RewriteRule ^([^/]*)/([^/]*)$ /?base=$1&page=$2 [L]
RewriteRule ^([^/]*)$ /?base=$1 [L]
That is because if it is kept in the order you have it, both localhost/?base=guest&page=register & localhost/?base=administrator will match the rule RewriteRule ^([^/]*)$ /?base=$1.
Having them in reverse order ensures that the first rule is matched only for localhost/?base=guest&page=register. It won't match the first rule for localhost/?base=administrator. I hope that helps.
You need to exclude your existent files and folders from the rule
RewriteEngine On
# if the request is a dir
RewriteCond %{REQUEST_FILENAME} -d [OR]
# or file
RewriteCond %{REQUEST_FILENAME} -f
#do nothing
RewriteRule ^ - [L]
RewriteRule ^([^/]*)/([^/]*)$ /?base=$1&page=$2 [L]
RewriteRule ^([^/]*)$ /?base=$1 [L]
So you can use this simple code:
RewriteEngine on
RewriteRule ^(\w+)$ index.php?base=$1 [L]
RewriteRule ^(\w+)/(\w+)$ index.php?base=$1&page=$2 [L]
\w will match symbols a-z, 0-9 and underscore _, I think those characters are enough for your case, but if you need expansion it will be easy
Also in this case you don't need to change your code, because you still get base and page parameters in the $_GET array
UPDATE:
to disable query string params page and base (other params may be needed) add these two lines to the code at the bottom:
RewriteCond %{THE_REQUEST} (\?|&)(page|base) [NC]
RewriteRule .* - [L,R=404]

Remove /page/ in url when opening pages

We have added a paging system inside our layout. When we go to /page/clan, the page about our clan gets displayed. (as its located in pages/clan.php).
To get /page, we used a htaccess script, which rewrites index.php?page=pagename into the /page/pagename I mentioned.
This is our current htaccess code for converting these urls:
RewriteEngine On
RewriteRule ^page/([^/]*)$ index.php?page=$1 [L]
However, We'd like to remove the /page part, so it's possible to just use /clan instead of /page/clan to open the clan page.
How can this be done and with what code?
Thanks!
Try :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)/?$ index.php?page=$1 [L,NC]
Rewrite condions make sure you don't rewrite any existing files or directories on the server.
[NC] flag makes the pattern case insensitive, so in you case example.com/fOo would also work.

.htaccess if statement?

I haven't worked with .htaccess too much. Looking to do something like this:
When user types in domain.com/path it is then pulled from domain.com/index.php/path/to/file
UNLESS
someones goes to domain.com/admin
How can an add a exception or if statement for a few words that i dont want to redirect?
Put a rule for the admin rewrite first and use [L] at the end to tell .htaccess this is the last rule it should follow. Then, put your other rules after it.
Example:
RewriteRule ^admin(/?)$ - [L]
RewriteRule ^(.*)$ /path/to/file.php?id=$1
Using the - after the match rule means it won't rewrite it, it'll just go to the path that was provided.
You need to add a RewriteCond rule to exclude stuff from the rewrite rule.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^admin
RewriteCond %{REQUEST_URI} !^index.php
RewriteRule ^(.*)$ /index.php/$1 [L]

URL Rewrite problem. (Many directory)

I'd like to make a htaccess file, which can make a good structure for my websites.
My .htaccess is now:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !\.(jpg|jpeg|gif|png|css|js|pl|txt)$
RewriteCond %{REQUEST_URI} !/admin
RewriteRule ^(.*)$ index.php?q=$1 [QSA]
(based on Sombat's comment, and about 30 try :P)
And I want to make this, with it:
for every elements but (jpg|jpeg|gif|png|css|js|pl|txt)
if domain.xx/admin redirect to the domain.xx/admin directory and don't make a rewrite at all
i mean: let me use domain.xx/admin/index.php?asd=1&asdd=2
else rewrite everything as rule one, to index.php.
Thanks for the help.
You can just add another RewriteCond directive after the one you have now that will exclude the admin directory.
RewriteCond %{REQUEST_URI} !^/admin/.*
That will prevent your RewriteRule from being applied if the RewriteCond matches your admin path. The order of RewriteCond and RewriteRule directives is important, so be sure to put it before the RewriteRule that you want it to affect.

Categories