Unlimited paired variables through .htaccess - php

This may be asked already but I'm struggling on here and can't figure it out,
I'm not really good with .htaccess
I'm working on an API and would like to accept multiple variables such as
http://www.website.com/api/CONTROLLER/person/id/1/sort/name/limit/2
and would like to obtain something like
$_REQUEST['CONTROLLER']=person;
$_REQUEST['id']=1;
$_REQUEST['sort']=name;
$_REQUEST['limit']=2;
I'm currently doing this through php using $_SERVER[REQUEST_URI] and explode, but would like to find out if there is a way to do it on .htaccess directly
If you know which one will perform best would be glad to hear it out!

Try:
RewriteEngine On
RewriteRule ^api/([^/]+)/([^/]+)(/.*)? /api/$3?$1=$2 [L,QSA]
Assuming that your php script is the index.php file in your /api/ directory. Otherwise, you'd need to also include (at the end):
RewriteCond %{QUERY_STRING} .+
RewriteRule ^api/$ /path/to/your/script.php [L,QSA]
Note that this relies on the mod_rewrite engine looping internally. There's a server setting which limits the maximum number of internal redirects, and if the URL is really long, it'll hit the internal recursion limit and return a 500. You can change this using the LimitInternalRecursion directive.

Related

Generic way to rewrite external /api/entity/1 URL to internal /api/entity.php/1 (or /api/entity.php?id=1)

With a API I'm trying to make in PHP I currently have these rewrite rules setup in the .htaccess file for the root directory of the API:
# Remove the php extension from the filename
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
This is so that requests to the API appear more "RESTful" - so instead of api/entity.php?id=5 it would be api/entity?id=5 - I'd like to go a step further though, and allow a request URL like api/entity/5 to successfully rewrite to api/entity.php/5 or api/entity.php?id=5.
I was experimenting with an apache rewrite rule something like this, where it has regex to detect a path like entity/{any number here}
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC]
RewriteRule ^(.+)(\/\d+)$ $1.php$2 [NC,L]
Where it would match entity/5 in two captures with entity and /5 and would then internally direct that to entity.php/5 - at which point in the php file I could do an explode on the request URI or something similar to that to get the value from the path.
But I don't really know enough about apache rewrites to fully implement this, as this rule doesn't work for whichever reason. I'm aware I could write hardcoded rewrite rules for each directory I would like to behave like this, but I'd really rather keep this generic.
If there is no real way to achieve what I want to here, then I'd rather just stick to paths like api/entity?id=5 than need to write a whole bunch of rewrite rules.
I was thinking as well, if there is a way to detect when a request doesn't match a directory (which would be what happens by default with a path like api/entity/5?) - it runs a different rewrite in this case - without running the first and causing it to try and write the now internally pointed URL, but again, I'm not sure how to go about implementing this.
Can someone with more experience point me in the right direction?
As Chris Hass highlighted, in this case implementing a PHP router of some variation probably makes more sense and is just easier.
Here are links to some examples I found for anyone in the future who stumbles onto this:
https://medium.com/the-andela-way/how-to-build-a-basic-server-side-routing-system-in-php-e52e613cf241
https://www.taniarascia.com/the-simplest-php-router/
https://www.educative.io/edpresso/how-to-create-a-basic-php-router
Obviously, if you're not intentionally using just PHP on its own like me, there's no reason you couldn't use a library or do this with Laravel etc to make your life even easier, why reinvent the wheel after all?

How to clean a url with php without using htaccess?

I have a problem with a project I'm doing with PHP and it's in the URLs.
When I load a script like index.php everything works fine, the problem is when I load a script that is located within two or more directories.
In the URL the scripts with the routes begin to be enmeshed
Here is an example of the problem I have
I need to load a script, even if it is in several levels of nesting, make its functionality and in the url is reflected as:
I need to have something like this
1:
I thank you in advance.
Regards
You can't use PHP to achieve this. PHP is not responsible for determining if PHP (let along a particular PHP script) will handle any given URL.
You have to configure your webserver to do it. Since you mention .htaccess but provide no further information about your server, I'm going to assume you are using Apache HTTPD.
For Apache, that means using mod_rewrite, Alias or something similar. You can put the configuration for those tools in .htaccess, but you don't want to and the documentation advises not to use them.
So put your mod_rewrite or Alias configuration in the main Apache configuration.
You're going to need an htaccess rule no matter what. However, it doesn't have to be a mod_rewrite rule. The reason you need this rule is because PHP is not responsible for the routing - it is merely responsible for the execution of your script.
The point of the rule is to direct apache and instruct it to execute the right script (in your case, script32.php) while keeping the request uri as intact as possible.
There are two ways around it, basically.
Way 1 (cleaner): mod_rewrite
This is pretty straightforward, the set of rules you need are as follows:
# If the requested file name is a valid file/inode
RewriteCond %{REQUEST_FILENAME} -f [OR]
# ...or a directory
RewriteCond %{REQUEST_FILENAME} -d
# ...then throw them straight on it
RewriteRule (.*) - [L]
# ...otherwise, redirect to script32.php with the full content of the request in query string
RewriteRule (.*) /welcome/script32.php?$1 [L]
The requested URL is now in $_SERVER['QUERY_STRING'] and you can now do whatever you like with it in PHP
Way 2: catchall
This does not rely on mod_rewrite and may therefore be slightly faster. However, technically, it's a cheap hack. The way around it is as follows:
ErrorDocument 404 /welcome/script32.php
The requested URL can now be found in $_SERVER['REQUEST_URI'] and is available for parsing in PHP. However, with this, you've also disabled "legit" 404 errors from being generated through apache - and should make sure to obey proper behaviour in PHP to compensate.

How to use directory names as options or parameters?

I don't even know how this method is called, I just know the behavior I want to achieve.
My example for this is Facebook. If you go to facebook.com/[username or id] you get to the profile page, but I can't imagine that they're creating a directory in their root folder and putting a index file in there for every user.
So how's the following behavior accomplished; You go to somepage.com/foo/bar/hello but actually you're requesting somepage.com/foo?bar=hello ?
Is this even possible with Apache and PHP?
I don't even know how this method is called, I just know the behavior I want to achieve.
That thing is called URI/URL and the local part of it is passed to a webserver. The webserver then processes the request.
Is this even possible with Apache and PHP?
Yes. Not even even. This is what a webserver is for. What happens on the server is entirely shielded by the HTTP protocol which knows only the URI/URL specification which does not regulate if and how that needs to match to concrete processes or files on the webserver.
For example with the Apache HTTP Server there is a famous module called Mod_Rewrite that does URL-Rewriting. Often in a fashion that the user with her browser does not take any notice of it.
Example configuration with a PHP file (Apache HTTPD):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
In a PHP script you can obtain the URI/URL by making use of special variables like $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'].
Commonly this is made with mod rewrite. There you can make a "path" to a variable of a script.
E.g. http://example.com/user/1/edit could be translated with mod rewrite to http://example.com/index.php?function=edit&userid=1
Such a rule would look like this:
RewriteEngine on
RewriteRule ^/user/([0-9]+)/([a-z]+)$ index.php=function=$2&userid=$1 [L]
The first line activated the rewrite module the second line has a regular expression which must match for rewrite the url internally. If you like you can also make that externally with an [R] modifier instad of the [L].
Have a look to the whole documentation to learn more.
The stuff in the breckets are so called flags which are also well documentated.
I hope that helps!

Can someone explain this strange mod_rewrite regex behavior

I've been working on a script for debugging mod_rewrite, and when testing their regex system I've had some strange results. I'm wondering if this is normal behavior for the mod_rewrite regex engine or if some part in my code is causing it.
Requested URL: http://myurl.com/path/to/something
.htaccess has: RewriteRule to where
Using my debugging system, the following is what happens when that RewriteRule is used:
path/to/something -> where/to/something
Shouldn't it be path/where/something???
Here's the full .htaccess file
RewriteEngine On
RewriteBase /ModRewriteTester
RewriteRule .* - [E=ORIG:$0]
RewriteRule to where
RewriteRule .* - [E=MODD:$0]
RewriteRule .* index.php
Then I've got a php script that's reading in the environmental variables $_SERVER['REDIRECT_ORIG'] and $_SERVER['REDIRECT_MODD'], that's where I'm getting the previously stated paths.
If anyone knows a better way to explicitly show how mod_rewrite's regex engine works I'm open to it. The initial question still stands though...
Your rule:
RewriteRule to where
...will rewrite a URL that matches to and replace it with the URL representing what would be a request to /where. It's possible in certain circumstances for mod_rewrite to try and re-add what Apache believes to be PATH_INFO, which could create a situation like the following:
path/to/somewhere -> PATH_INFO = /to/somewhere
path/to/somewhere -> /where
(append PATH_INFO) -> /where/to/somewhere
To check if this is the case in your scenario, you can add the DPI flag to the RewriteRule to discard the PATH_INFO if it exists. This would look like this:
RewriteRule to where [DPI]
In this case, you would end up with just the URL /where. If you wanted to replace to with where while retaining the rest of the URL, you would need a rule more like this:
RewriteRule (.*?/)?to(/.*)? $1where$2
As far as debugging your rule set goes, if you have access to the Apache configuration you're much better off using the RewriteLog directive with a sufficiently high RewriteLogLevel. If you don't have access to the configuration, you're pretty much limited to doing something similar to what you're trying to do now.

What's the best way to get rid of .php suffix in url strings so they look pretty? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Remove .php extension with PHP
What's the best way to get rid of .php suffix in url strings so they look pretty?
Thank you in advance;-)
Use apache mod_rewrite (rewriting rules)
http://roshanbh.com.np/2008/02/hide-php-url-rewriting-htaccess.html
Make sure your apache installation has mod_rewrite enabled (will be in httpd.conf, or one of the files linked there, mods-enabled or such) and look into how routing works in cakePHP.
Couple of tips - the rewrite rules are found in the .htaccess files (make sure you don't have a unicode BOM if the server gives a 500 error) and if you do find you need those $_GET paramters, [qsappend] on your rewrite rule should pass them along. If you still get 500s the compilation errors on regexes can be found in apache's error log, invaluable for debugging.
Might be easier to do a simple project with mod_rewrite first, to learn how it works, as the combination of rewrite and routing in cake can get pretty complex pretty fast.
Options +MultiViews
in the Apache configuration.
Here is a gentle introduction into mod_rewrite.
The best way to do so (at least for me) is:
Use just one file to receive all request. In most of the cases it will be the index.php file.
Then, use mod_rewrite rules like this:
:
RewriteEngine On
RewriteBase /the_base_dir_of_your_app/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /the_base_dir_of_your_app/index.php [L]
Then, you can analize the URL using functions like basename($_SERVER['REQUEST_URI']); in order to decide what to do.
Use mod_rewrite - or start using ASP.NET MVC 2 :)
If you use a framework, like CakePHP (or any other) it will do it for you. For free. Right now.
.htaccess:
Permalinks
RewriteEngine on
Remove www
RewriteCond %{HTTP_HOST} ^www.yourdomain.com [NC]
RewriteRule (.*) http://yourdomain.com/$1 [R=301,L]
Links
RewriteRule ^faq$ /faq.php [L]
RewriteRule ^donations$ /donations.php [L]
RewriteRule ^contact$ /contact.php [L]
so they look pretty?
Beauty is in the eye of the beholder. It depends when you consider 'pretty'. A lot also depends on how much you want to get away from the conventions that make a working system possible and the constraints in terms of reconfiguring your site.
While others have mentioned using mod_rewrite, or URL parsing or other such approaches I'm not a fan of these - in addition to being very specific to the type of webserver the code is running on they also break the simple 1:1 mapping beween paths in URIs and paths on the webserver's filesystem.
You could just substitute '.php' with an extension of your choice...but that hardly meets my interpretation of 'pretty'.
The approach I take is to have every script (or at least every script with is intended to be entry point to generaeing a web page) is named as index.php and exists in its own uniquely named directory. The main reason for doing this is nothing to do with making the URL look nice but rather to make the codebase more manageable - I also have strict standards about the naming and placement of include files.
HTH
C.

Categories