For my own MVC I need to read the request URI from the global variables ($_GET or $_SERVER).
First I thought to read it from $_GET array. But then I discovered that it's contained in the $_SERVER array as well.
So, I would like to ask, from which global array should the request URI be read?
An example:
The URI could have the following structure:
http://local.mvc/PsrTest/testRequest/123?var=someval
with:
PsrTest as controller name;
testRequest as action name;
123 as argument for the controller action;
var=someval as some query string key/value pair;
By applying a RewriteRule in ".htaccess", it will be translated to:
http://local.mvc/index.php?url=PsrTest/testRequest/123&var=someval
and it will be saved in the following items of the $_GET and $_SERVER arrays:
------------
$_GET array:
------------
'url' => 'PsrTest/testRequest/123'
'var' => 'someval'
---------------
$_SERVER array:
---------------
'HTTP_REFERER' => 'http://local.mvc/PsrTest/testRequest/123?var=someval'
'REDIRECT_QUERY_STRING' => 'url=PsrTest%2ftestRequest%2f123&var=someval'
'REDIRECT_URL' => '/PsrTest/testRequest/123'
'QUERY_STRING' => 'url=PsrTest%2ftestRequest%2f123&var=someval'
'REQUEST_URI' => '/PsrTest/testRequest/123?var=someval'
Thank you for your time!
But if you want to use .htaccess this is a start.
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
# One param
RewriteRule ^/?([^/]*)$ index.php?section=$1 [NC,L]
# Two params
# IE: search/12345
RewriteRule ^edituser/([a-zA-Z0-9]+)/?$ index.php?section=edituser&id=$1 [NC,L]
# Three params
# IE: search/12345/676767
RewriteRule ^editcontact/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/?$ index.php?section=editcontact&contactID=$1&reservationID=$2 [NC,L]
This is a small example from an older program I wrote.
As #teresko suggested, .htaccess are not always a possibility. Then it makes indeed no more sense (at least for me) to write RewriteRules in .htaccess, which translate the given URI into query string parameters. It will be sufficient to:
Just write a simple rule, like RewriteRule ^ index.php [L] in .htaccess;
Just parse the $_SERVER['REQUEST_URI'] value in PHP, in order to get the URI components needed to call a controller action and to pass the corresponding parameters to it.
I'm grateful to all the users who helped me finding my answer. Thanks!
Related
assume that i'm having a URL like this
testingQuiz.com/my_test_link.php?id=4&name=test
Now I need to rewrite the above URL like this,
testingQuiz.com/4/test.html
My question is, how can I achieve that by .htaccess URL rewriting?
Something like the following perhaps should work, this is not fully tested btw but preliminary tests show it does as expected - though perhaps the second style redirect could be refined.
/* turn on url rewriting */
RewriteEngine On
/* set the level for the rewriting, in this case the document root */
RewriteBase /
/* match 2 parameters in querystring - the first is numeric and the second is alphanumeric with certain other common charachters */
RewriteRule ^([0-9]+)/([a-zA-Z0-9_-]+)\.html$ my_test_link.php?id=$1&name=$2 [NC,L]
That should allow you to write your urls / links in the form http://www.example.com/23/skidoo.html and for the $_GET variables to be interpreted as:
$_GET['id'] => 23, $_GET['name'] => skidoo
If you need to automagically redirect the user from your original style querystring to the new, nicer style url you could try adding the following after the rule above:
RewriteCond %{THE_REQUEST} /(?:my_test_link\.php)?\?id=([^&\s]+)&name=([^&\s]+) [NC]
RewriteRule ^ %1/%2\.html? [R=302,L,NE]
That way, if a user enters the url http://www.example.com?id=23&name=skidoo it will redirect to http://www.example.com/23/skidoo.html
I'have this rewrite condition that redirect all the request of non-existing files to the app.php in parent directory.
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1#%{REQUEST_URI} ([^#]*)#(.*)\1$
RewriteRule ^(.*)$ %2../app.php [L]
In the last line (rewriterule) the value of $1 is the path relative to the dir where .htacces is, in order to make it portable ( found here: http://linlog.skepticats.com/entries/2014/08/Using_RewriteBase_without_knowing_it.php ).
That is : calling http://localhost/myapp/public/test123/r.txt I will get test123/r.txt in $1 variable (considering that .htaccess is in public/).
I would like to pass the value of $1 to the app.php, a common solution would be to append it as a query string:
RewriteRule ^(.*)$ %2../app.php?__path=$1 [L]
In this way I have __path as a GET variable (PHP: $_REQUEST["__path"]) , but how it works with other kind of requests like POST (query string should not be there) ?
A more clean solution would be to put $1 in a HTTP custom header but, how can I set a custom header, say MYAPP_PATH to $1 value through .htacess ?
To start with your comment:
I've noticed that the trick ?__path=$1 overrides all the querystring that I pass in the original URL.
You forgot to set the QSA flag.
Second to the core question:
In this way I have __path as a GET variable (PHP: $_REQUEST["__path"]) , but how it works with other kind of requests like POST (query string should not be there) ?
This just works fine. GET-parameters are just popularly called that, they're actually query string parameters and can be passed with any HTTP verb, from GET and POST to PUT and DELETE. So if you POST to a URL with query string parameters you can still read them from $_GET just fine.
Final point, as the above solves all your issues: please do not use $_REQUEST. It's really REALLY bad practice, and may lead to obscure security and stability issues. Just use $_POST, $_GET et al instead.
I have a URL http://localhost/index.php?user=1. When I add this .htaccess file
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^user/(.*)$ ./index.php?user=$1
I will be now allowed to use http://localhost/user/1 link. But how about http://localhost/index.php?user=1&action=update how can I make it into http://localhost/user/1/update ?
Also how can I make this url http://localhost/user/add ?
Thanks. Sorry I am relatively new to .htaccess.
If you want to turn
http://www.yourwebsite.com/index.php?user=1&action=update
into
http://www.yourwebsite.com/user/1/update
You could use
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^user/([0-9]*)/([a-z]*)$ ./index.php?user=$1&action=$2
To see the parameters in PHP:
<?php
echo "user id:" . $_GET['user'];
echo "<br>action:" . $_GET['action'];
?>
The parenthesis in the .htaccess are groups that you can call later.
with $1, $2, etc.
The first group I added ([0-9]*) means that it will
get any numbers (1, 34, etc.).
The second group means any characters
(a, abc, update, etc.).
This is, in my opinion, a little bit more clean and secure than (.*) which basically mean almost anything is accepted.
you can write something like this:
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)$ /index.php?user=$1&action=$2 [L]
a simple way is to pass only one variabe to index.php like this
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^(.*)$ index.php?data=$1 [QSA]
and in your index.php file you do this
$data = expload("/",$_GET['data']);
$user = $data[1];
$action = $data[2];
this one works for all cases, when you try to pass many variables, it doesn't work in case you do something like this though
http://localhost/user/add/12/54/54/66
the last variable always takes the value add/12/54/54/66
Since you tagged this with PHP, I'll add a little perspective from what I did, and it may or may not help you.
You can, of course, write solely in .htaccess, being careful about order. For instance, let's say that you have:
RewriteRule ^user/([0-9]+)/update$ ./index.php?user=$1&action=update
RewriteRule ^user/([0-9]+)$ ./index.php?user=$1
Then it should, upon receiving
http://localhost/user/1/update
go to
http://localhost/index.php?user=$1&action=update
and not
http://localhost/index.php?user=$1
Now, what I did instead was push everything to index.php?q=$1
RewriteRule ^(.*)$ index.php?q=$1
Then I used index.php to handle how the query was broken up. So let's say someone enters
http://www.example.com/user/18239810/update
this would go to
http://www.example.com/index.php?q=user/18239810/update
From there, explode the query string along the first / to give user and 18239810/update.
This would tell me that I need to pass 18239810/update to the user controller. In that controller, I again explode the argument into the user id and command, and I can switch on the command to tell how to load the page, passing the user id as an argument to the update function.
Very quick and dirty example (index.php):
<?php
$getString = explode('/', $_GET['q'], 1);
$controller = $getString[0].'Controller';
require_once('/controllers/'.$controller.'.php');
$loadedController = new $controller( $getString[1] );
?>
Of course, this means that constructors all must take a string argument that will be parsed for acceptable values. You can do this with explodes and switch statements, always defaulting back to the standard front page to prevent unauthorized access based on random guessing.
For /user/add you will need to do a separate rule because you have no "middle parameter". So:
RewriteRule ^user/add$ ./index.php?action=add [L,QSA]
You can then do additional rules for URLs that contain additional parameters:
RewriteRule ^user/([0-9]+)/([A-Za-z]+)$ ./index.php?user=$1&action=$2 [L,QSA]
This will allow you to perform actions on existing users. E.g. /user/1/update
Thanks for the idea #denoise and #mogosselin. Also with #stslavik for pointing out some of the drawback of my code example.
Here's how I do it:
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^user/([0-9]*)/([a-z]*)$ ./index.php?user=$1&action=$2
RewriteRule ^user/([a-z]*)$ ./index.php?user&action=$1
by using var_dump($_GET); on the link localhost/user/1234/update I got
array (size=2)
'user' => string '1234' (length=4)
'action' => string 'update' (length=3)
while localhost/user/add
array (size=2)
'user' => string '' (length=4)
'action' => string 'update' (length=3)
which is my goal. I will just only do other stuffs under the hood with PHP.
Its simple just try this out !
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^game/([0-9]+)/([_-0-9a-zA-Z]+)/?$ index.php?user=$1&action=$2 [L,NC]
Thats it !!
Try this it is very simple:
Options +FollowSymLinks
RewriteEngine on
RewriteRule index/user/(.*)/(.*)/ index.php?user=$1&action=$2
RewriteRule index/user/(.*)/(.*) index.php?user=$1&action=$2
I'm trying to create a url routing script for my new CMS but must confess that regex isn't my strong side. So far i keep running into errors or no results.
What i'm trying to accomplish is using certain tags like :id :year :slug etc...
Can anybody help me out or guide me to the right direction with this, that is how to use preg_match or similar functions to find the right "url pattern"? Google has not been doing it job for once :S
ADDED
Example url http://www.mysite.com/post/2011/08/15/title-of-a-blogg-post/
If i have a route database and one pattern is for example post/:year/:month/:day/:slug i want it to match this pattern and call a certain controller, action and in this example a certain article.
The regex array i created looks like
$patterns = array(
":id" => "/^[0-9]*$/",
":year" => "/^([0-9]{4})*$/",
":year_short" => "/^([0-9]{2})*$/",
":month" => "/^([0-9]{2})*$/",
":day" => "/^([0-9]{2})*$/",
":slug" => "/^[a-zA-Z0-9 -]*$"
);
I reckon i need to replace :id to /^[0-9]*$/ and afterwards run a preg_match to find if the url pattern exists in my routes table. However i don't know if i'm using the right regex patterns or just completely lost.
My .htaccess file is (because i need to use $_GET as well)
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
I use this basically to fetch the url and leave out $_GET variables.
$route_orginal = trim($_SERVER["REQUEST_URI"]);
if(strpos($route_orginal, "?")!=FALSE) {
list($route_orginal, $get_orginal) = explode("?", trim($_SERVER["REQUEST_URI"]));
}
if( substr($route_orginal,(strlen($route_orginal)-1),strlen($route_orginal)) == "/") {
$this->routes = substr($route_orginal,1,(strlen($route_orginal)-2));
} else {
$this->routes = substr($route_orginal,1,strlen($route_orginal));
}
I'm not sure what you are trying to accomplish.
But if you want a URL like www.mysite.com/tags/id-year-slug
where every tag is seperated by a hyphen, you could do like this:
First, you need a .htaccess file in your root to create pretty urls.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/tags/([A-Za-z-]+)$ index.php?tags=$1 [L,QSA]
Then in your index, you explode the tags by the - delimiter:
$tags = explode('-',$_GET['tags']);
Now you have an array of tags, which you can use for your sql and the url is pretty - high five!
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'].