Routing URL Path with PHP and Apache - php

I am trying to create a nice url structure for my site.
My router class will only work if the url is in the style of ?something=value.
How do I get it so it will work like:
/something/value
In my .htaccess I have:
Options FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(js|txt|gif|jpg|png)$ index.php?$1 [L,QSA]
And in my router class I'm making:
class init {
function __construct()
{
$URL = substr($_SERVER['REQUEST_URI'], 19) ;
$URLElements = explode('/', $URL) ; // Adjust if needed.
$class = $URLElements[0] ;
$method = $URLElements[1] ;
if(($t = substr_count($URL, '/')) > 1)
{
for($i=2;$i<$t+1;$i++) {
echo $URLElements[$i].'<br />';
}
}
}
}
Thanks to Jason, my .htaccess is now just:
FallbackResource /t2013/public_html/index.php

For a quick way to handle Front-end Controllers with Apache, use FallbackResource and parse the URL with PHP.
FallbackResource /index.php

htaccess should be something like this
RewriteEngine on
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)$ $1.php?$2=$3 [QSA]
so for example
/home/something/value would be redirected to /home.php?something=value
Give it a go, not completely sure on this but have done something similar before.

From a PHP perspective, you would just need to adjust your init class to key off of $_SERVER['REQUEST_URI'] instead of $_SERVER['QUERY_STRING']. You are not showing your full logic here, but my guess is that you would simply trim the first / and then explode the URI on / to get at the component parts.
From an .htaccess standpoint, you could just change your last line to be:
RewriteRule ^.*$ index.php [L,QSA]
You don't need to specifically detect images/css/js here as that RewriteCond already makes exceptions to the rewrite rule for any actual files or directories. Note that in the RewriteRule I did leave the Query String Append (QSA) flag in place in case you still wanted to do something like /controller?some=string&of=data If you don't anticipate using query strings at all with your new URI's, then you can omit this flag.

Related

How to handle dynamic routes in PHP?

I'm creating an API via PHP. I need to let users see a particular user. For example if someone goes to mysite.com/users/2, he must get the data about the user with id=2.
This is my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.css$
RewriteRule ^([-/_a-zA-Z0-9\s]*)$ index.php?url=$1 [QSA,L]
The variable $url in index.php contains the whole url (for example users/2)
I use something like if($url == "users"){ //code } for routes, but what can I do with id that can be various?
Since you have everything in $url, you can just use explode()
Here's an example:
$url = "users/1234";
$url_array = explode("/", $url, 2);
echo $url_array[1];
This doesn't handle any errors, and as you stated in the comments, you'd need to implement those. So, unless this is a very small project it does seem safer, more maintanable, faster, etc. to use a framework like Laravel, or perhaps a micro-framework Lumen or Slim if you only need a few features.
You dont have to include the url in the RewriteRule:
# Redirect all requests to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Then in your index.php:
$urlparts = explode("/", substr(#$_SERVER['PATH_INFO'], 1));
if($urlparts[0] == 'users'){
//find user with id $urlparts[1]
}

.htaccess and PHP beautify URL

I am trying out an alternative approach to beautiful URLs with PHP:
$request = explode("/", substr(#$_SERVER['PATH_INFO'], 1));
The above snippet will let me use URLs that are something like "www.example.com/index.php/article/how-to-diy" where "/article/how-to-diy" is the URL parameter.
I'd really like to lose the "index.php", though, and I am in no way a .htaccess-wiz, so I could use some help on making a rewriterule that will change my URLs into "www.example.com/article/how-to-diy".
I've looked around on SO and the examples I found were all related to a classic parameter syntax (i.e. "index.php?page=12"), which is not the solution I am after.
I'm accustomed to the typical MVC/Wordpress way of handling urls...less work in htaccess and all the work in the url router. I'll give an example:
.htaccess
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
</IfModule>
Then, within index.php call a routing mechanism that parses your urls and produces the appropriate page. But don't use PATH_INFO, you need to know what is being requested:
$request = explode("/", #$_SERVER['REQUEST_URI']);
EDIT:
If the script (index.php) and .htaccess are not located in the document root, the RewriteRule should reflect this:
RewriteRule . /path/to/index.php
And then the routing mechanism should simply loop through $request, in order to find the parts it needs.

Pretty URL via htaccess using any number of parameters

Actually i have this URL:
http://www.example.com/index.php?site=contact&param1=value1&param2=value2&param3=value3
But i want to have this URL format:
http://www.example.com/contact/param1:value1/param2:value2/param3:value3
So the "contact" goes to variable $_GET["site"] and rest of parameters should be able to access via $_GET["param1"], $_GET["param2"] etc. The problem is, it has to work with any number of parameters (there could be param4 or even param50 or any other name of parameter). Is it possible via htaccess to cover all these cases?
Mod_rewrite has a maximum of 10 variables it can send:
RewriteRule backreferences:
These are backreferences of the form $N (0 <= N <= 9), which provide access to the grouped parts (in parentheses) of the pattern, from the RewriteRule which is subject to the current set of RewriteCond conditions.
mod_rewrite manual
so what you desire is NOT possible with htaccess only. a common way is to rewrite everything to one file and let that file determine what to do in a way like:
.htaccess
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,NC]
index.php
$aUrlArray = explode('/',str_ireplace(',','/',$_SERVER['REQUEST_URI'])); // explode every part of url
foreach($aUrlArray as $sUrlPart){
$aUrlPart = explode(':',$sUrlPart); //explode on :
if (count($aUrlPart) == 2){ //if not 2 records, then it's not param:value
echo '<br/>paramname:' .$aUrlPart[0];
echo '<br/>paramvalue' .$aUrlPArt[1];
} else {
echo '<br/>'.$sUrlPart;
}
}
Garytje's answer is almost correct.
Actually, you can achieve what you want with htaccess only, even if this is not something commonly used for that purpose.
Indeed, it would be more natural to delegate the logic to a script. But if you really want to do it with mod_rewrite, there are a lot of techniques to simulate the same behaviour. For instance, here is an example of workaround:
# Extract a pair "key:value" and append it to the query string
RewriteRule ^contact/([^:]+):([^/]+)/?(.*)$ /contact/$3?$1=$2 [L,QSA]
# We're done: rewrite to index.php
RewriteCond %{QUERY_STRING} !^$
RewriteRule ^contact/$ /index.php?site=contact [L,QSA]
From your initial example, /contact/param1:value1/param2:value2/param3:value3 will first be rewritten to /contact/param2:value2/param3:value3?param1=value1. Then, mod_rewrite will match it again and rewrite it to /contact/param3:value3?param1=value1&param2=value2. And so on, until no pair key:value is found after /contact/. Finally, it is rewritten to /index.php?site=contact&param1=value1&param2=value2&param3=value3.
This technique allows you to have a number of parameters greater than 9 without being limited by mod_rewrite. You can see it as a loop reading the url step by step. But, again, this is maybe not the best idea to use htaccess only for that purpose.
This is entirely doable using some creative htaccess and PHP. Effectively what you are doing here is telling Apache to direct all page requests to index.php if they are not for a real file or directory on the server...
## No directory listings
IndexIgnore *
## Can be commented out if causes errors, see notes above.
Options +FollowSymlinks
Options -Indexes
## Mod_rewrite in use.
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
After this all you need to do is go into PHP and access the full user requested URL structure using the $_SERVER['REQUEST_URI'] superglobal and then break it down into an array using explode("/", $_SERVER['REQUEST_URI']).
I currently use this on a number of my sites with all of the sites being served by index.php but with url structures such as...
http://www.domain.com/forums/11824-some-topic-name/reply
which is then processed by the explode command to appear in an array as...
0=>"forums", 1=>"11824-some-topic-name",2=>"reply"
Try this..
.htaccesss
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /index.php [L,QSA]
index.php
$uri = $_SERVER['REQUEST_URI'];
$uri_array = explode( "/", $uri );
switch ( $uri_array[0] ) {
case '':
/* serve index page */
break;
case 'contact':
// Code
break;
}
This is doable using only htaccess with something along the lines of...
([a-zA-Z0-9]+):{1}([a-zA-Z0-9]+)
([a-zA-Z0-9]+) will match alpha-numeric strings.
:{1} will match 1 colon.
Expanding from there will probably be required based on weird URLs that turn up.

How i hide my page name in url with .htaccess?

My Code
RewriteRule ^walls/([0-9a-zA-Z-_]+) display.php?art_nm=$1 [NC,L]
What i get is:
website.com/walls/i_love_coding
what i need is:
website.com/i_love_coding
You probably should use the front controller pattern. Basically, you give every request to your front controller which decide what to do.
.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
</IfModule>
Then, use your "front controller" to forward request to correct script according to $_SERVER['REQUEST_URI'].
index.php
<?php
$name = trim($_SERVER['REQUEST_URI'], '/');
$page = find_page_by_name($name);
if ($page) {
require $page;
} else {
require __DIR__.'/errors/404.php';
}
Be carrefully in the find_page_by_name function to not return the path of an unauthorized file; you should ensure your path is within a specific directory (see realpath and strpos).
For example, an attacker could try to get http://example.com/../../etc/passwd !!!
For more complex routing, you should probably try a micro-framework like Silex or Slim.

htacess url rewrite? on a php get system

I use the code below to basically go to my pages. How it works is I put index.php?req=pagename and it will check my protected folder to see if the file is there if it is then it goes there. I need a mod rewrite so that it doesnt show all that index.php?req=pagename and just shows /pagename
require_once("protected/header.php");
if (isset($_GET['req'])) {
$req = $_GET['req'];
} else {
$req = "overall";
}
require_once("protected/$req.php");
require_once("protected/footer.php");
Your code allows any php file (barring safemode/open_basedir restrictions) to be parsed and executed. You need to escape that input first, even if it's something as rudimentary as removing slashes, tildes and periods.
As far as rewrite goes, simply create a .htaccess file in your document root along the lines of:
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?req=$1 [QSA,L]
</IfModule>
You will have to use POST instead of GET if you want a clean dynamic url. Your question though doesn't make much sense.

Categories