How to access query string parameters after "Cleaning" your PHP REST API? - php

To give some context, I initially started out with my api looking like this:
http://myserver/api.php?action=projects
In my api.php file I have a simple if statement to detect the action, and then react accordingly:
if (isset($_GET["action"])
{
switch($_GET["action"])
{
case "projects"
dostuff();
break;
case "otherstuff"
dootherstuff();
break;
...
}
}
However, I of course wanted to clean this up, so I could go to this url:
http://myserver/api.php/projects
and get the same outcome. I was able to accomplish this by reading up on a previous SO post:
Using Clean URLs in RESTful API
And ultimately got it working by making an .htaccess file in my root directory and using the rewrite engine like so:
RewriteEngine On
RewriteRule ^action/([^/\.]+)/?$ api.php?action=$1 [L]
This worked great! Except for one problem, because I am using the clean URL, it no longer seems to recognize the GET parameter exists.
I've found I can use
$_SERVER['REQUEST_URI'];
And then parse the URL to get my parameters. I don't see how this could work out though once I start introducing multiple parameters. Is there something I'm missing here, or do I need to look at it a different way and change how I format the parameters instead?

You can use these rules:
RewriteEngine On
RewriteRule ^(?:action|api\.php)/([^/.]+)/?$ api.php?action=$1 [L,NC,QSA]

Change to this:
RewriteEngine On
RewriteRule ^action/([^/\.]+)/?$ api.php?action=$1 [L, QSA]
You need the QSA parameter to keep the querystring intact. So now this is possible:
/action/projects/?my=name
Or you can do this:
RewriteEngine On
RewriteRule ^action/([^/\.]+)/([^/\.]+)/?$ api.php?action=$1&method=$2 [L, QSA]
RewriteRule ^action/([^/\.]+)/?$ api.php?action=$1 [L, QSA]
Now you will have these urls:
/action/projects/add/
/action/projects/

Related

.htaccess - Rewrite with 3 variables but after that get the rest of the URL

So I'm currently using my .htaccess to write my URL to be more URL friendly.
But I'm having trouble getting the fourth variable that could be more folders. I'll try and explain it as best I can below.
So at the moment I have the following URL working:
www.mysite.co.uk/first/second/third
Now for this I am using the rewrite rule:
RewriteRule ^e/([a-zA-Z0-9-/]*)/([a-zA-Z0-9-/]*)/([a-zA-Z0-9\-\/]*)$ index.php?var_1=$1&var_2=$2&var_3=$3 [L]
My problem comes when I one of the following happens:
www.mysite.co.uk/first/second/third/fourth
www.mysite.co.uk/first/second/third/fourth/fifth
www.mysite.co.uk/first/second/third/fourth/fifth/sixth
From the above I want the following variables to be returned:
$_GET['var_1'] = first
$_GET['var_2'] = second
$_GET['var_3'] = third/fourth
OR
$_GET['var_3'] = third/fourth/fifth
OR
$_GET['var_3'] = third/fourth/fifth/sixth
So basically I always have a 'var_1' and 'var_2' set but the third variable can be the rest of the URL.
I hope this makes sense and that it's possible.
I'm not sure why you your rule starts with ^e/
if your urls will be in format : www.mysite.co.uk/e/first/second/third/fourth
then use this regex:
RewriteRule ^e/([a-zA-Z0-9-]+)(/([a-zA-Z0-9-]+))?(/([a-zA-Z0-9-/]*))?$ index.php?var_1=$1&var_2=$3&var_3=$5 [L]
If you need it without /e/ at start www.mysite.co.uk/e/first/second/third/fourth
then remove /e/ from start
RewriteRule ^([a-zA-Z0-9-]+)(/([a-zA-Z0-9-]+))?(/([a-zA-Z0-9-/]*))?$ index.php?var_1=$1&var_2=$3&var_3=$5 [L]
Example above will work even with url-s like /first and /first/second but if you don't need it and you want to have this rule just in case of 3 or more params then you can simplify rule:
RewriteRule ^([a-zA-Z0-9-]+)/([a-zA-Z0-9-]+)/([a-zA-Z0-9-/]+)$ index.php?var_1=$1&var_2=$2&var_3=$3 [L]

.htaccess - redirect individual urls to url with query string

I'm looking to do the opposite of a common query with .htaccess files.
I want to redirect a standard url to a url with a query string, similar to below:
test.com/directory/pagename
to:
test.com/template?id=1
I don't require pattern matching of any form, I just want to write out a separate redirect for each one. For example:
test.com/colours/red = test.com/template?id=5
test.com/colours/yellow = test.com/template?id=3
Hopefully this makes some sense.
You can use this code in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteRule ^colours/yellow/?$ template?id=3 [L,NC,QSA]
RewriteRule ^colours/red/?$ template?id=5 [L,NC,QSA]

Custom URL with PHP

I have a small question to ask. Is it possible, via php or htaccess, to change a url like: miodominio.com/users.php?idu=x into something like miodominio.com/username ?
I want it to be Facebook style...Where "username" is the username chosen by idu = x.
There are multiple ways to solve this problem, but here's one that always suits my needs.
Guide all your URL requests through the index.php first and resolve the request in your PHP code second.
1) Use an .htaccess file to direct all URL's through index.php. You'll find one way here by the CodeIgniter framework and a more advanced explanation here. I recommend the CodeIgniter .htaccess guide first if you're inexperienced with .htaccess.
2) Second, use the $_SERVER variable in PHP to extract the URL. Probably with the help of the $_SERVER['REQUEST_URI'], you'll find '/username/' which you can then use to extract the user's data and serve it to them.
Good luck and beware of URL injections using this method.
You need to use apache's mod_rewrite for this. It can translate miodominio.com/username to miodominio.com/users.php?idu=x. There are some good guides about this which are easy to find with Google.
You can try to use this mod_rewrite pattern (add it to the .htaccess):
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)$ users.php?idu=$1
RewriteRule ^([a-zA-Z0-9_-]+)/$ users.php?idu=$1
you have to write a clean URL in your .htaccess file like :
RewriteEngine On
RewriteRule ^([a-zA-Z0-9]+)/$ users.php?idu=$1
Put the following in your .htaccess
RewriteEngine on
RewriteRule ^([a-z0-9_-]+)/?$ /users.php?idu=$1 [NC]
The [NC] will make it case-insensitive, if you accept only lowercase username, remove the [NC] from the last.

Use SO's URL format for $_GET

StackOverflow has a very neat, clean URL format. It looks the same as a directory structure, but there can't be a directory for each question on here! My question is this:
How can I get http://www.site.com/sections/tutorials/tutorial1, for example, to stay like that in the address bar, but convert it to a $_GET request for PHP to mess around with?
I could use a .htaccess file, but I don't want the URL being rewritten - I'd like it to remain clean and friendly. Is my only option here to use PHP's string splitting functions to get some pretend $_GET data?
Thanks,
James
What about this, using .htaccess to split the URL up, the URL won't change but instead point to index.php with various $_GET variables, this could could be increased to cover more URL sections.
# turn rewriting on
RewriteEngine on
# get variables in this order, [object], [object,action], [object,action,selection]
RewriteRule ^([^/\.]+)/?$ /index.php?object=$1 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ /index.php?object=$1&action=$2 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /index.php?object=$1&action=$2&selection=$3 [L,NC,QSA]
A PHP Rest framework could do this for you, so I refer you to this question. Most of the frameworks won't load the data from $_GET, but will offer a similar and equally convenient way to read it.
It's actually a RESTful way of building your URI's. Not only SO applies this pattern. I recommend to not re-invent the wheel by taking a look at this question.
In addition you could switch over to a RESTful framework such as CakePHP or CodeIgniter, which are configured by default to use the RESTful pattern.
$_GET does not contain the path compontents from the URL, only the parameters that eventually follow the ?. You could use
$parts = explode('/', pathinfo($_SERVER['REQUEST_URI'], PATHINFO_DIRNAME));
var_dump($parts);
However it seems you should have a read on URL rewriting e.g. with mod_rewrite. "I don't want the URL being rewritten - I'd like it to remain clean and friendly" ... The rewriting happens on the server. The user never sees the "ugly" result.
If you don't want to use mod rewrite the best solution would be using regular expressions agains the $_SERVER['REQUEST_URI'] variable.
i.e:
preg_match('|/(.*)/(.*)|', $_SERVER['REQUEST_URI'], $match);
$_GET['param1'] = $match[1];
$_GET['param2'] = $match[2];
If you want to setup a capture all php script. IE if the script request doesn't exist use a default script, use mod-rewrite to redirect everything to one script i.e. the zend framework (and most of the PHP MVC framework) use this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
I think that could be a bit cumbersome.

Easy mod_rewrite - So I'll never have to think about it again

Not sure how you'll take this question but...
Whenever I try to make my URLs look pretty I always end up messing around for too long and it's simply not worth the trouble. But the end effect is good if it were a simple task.
So what I want to do is create a method which in the end would achive something like...
index.php?do=user&username=MyUsername //This becomes...
/user/MyUsername //...that
index.php?do=page&pagename=customPage //And this becomes...
/page/customPage //...that
index.php?do=lots&where=happens&this=here //This also becomes...
/lots/happens/here //...that
index.php?do=this&and=that&that=this&and=some&more=too //And yes...
/this/that/this/some/more //This becomes this
So then I just make a nice .htacess file that I'll never have to look at again. Everything will be better in the world because we have pretty URLs and my head didn't hurt in the making.
You can use a different approach of throwing the url in a single parameter, and parse it in your application.
So the apache rewrite rule would look like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
which will convert your urls as follows:
/user/MyUsername => index.php?q=/user/MyUsername
/page/customPage => index.php?q=/page/customPage
...
In your app, you then have a $_GET['q'] variable, which you can split by '/', and have your arguments in order. In PHP it would be something like:
$args = explode('/', $_GET['q']);
$args will be an array with 'user', 'MyUserName', etc.
This way you will not have to touch your .htaccess again, just your app logic.
For /user/MyUsername ==> index.php?do=user&username=MyUsername and /page/customPage ==>
index.php?do=page&pagename=customPage, you can use:
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)$ index.php?do=$1&$1name=$2 [L]
But I don't think you can write a catch-all rule for /lots/happens/here and /this/that/this/some/more because you need to tell mod_rewrite how to translate the two urls.
Remember, mod_rewrite has to translate /lots/happens/here into index.php?do=lots&where=happens&this=here and not the other way around.
The best approach would be to delegate your application to generate the “pretty URLs” as well as parse and interpret them and to use mod_rewrite only to rewrite the requests to your application with a rule like this one:
RewriteRule %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
This rule will rewrite all requests that can not be mapped directly to an existing file to the index.php. The originally requested URL (more exact: the URL path plus query) is then available at $_SERVER['REQUEST_URI'].

Categories