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.
Related
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.
it's my first post, so tell me if i've done something wrong.
i'm trying to understand logic of big routers on github and frameworks.
I understand to routers that works like this:
folder structure:
*controllers/Home.php
*index.php
index.php file, orientation code:
$uri = www.xyz.com/home/default/param;
# get parts from url
$parts = explode("/", $uri);
# call controller
$controller_class = "controller_namespace\\".$parts[0];
$controller = new $controller_class;
call_user_func_array(array($controller, $parts[1]), $parts[2]);
.htaccess file:
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
so on page www.xyz.com/home/default/param is called controller class home and func. default with params, in filestructure you are still on index.php file, only different controller classes is being called by url.
So, routers that i want understand works like:
class Home{
Router::get("/default", function(){
echo 'Hello';
});
Router::Dispatch();
}
From code that i found on github here etc. i think, the Router loads all the functions from controller and execute that one which match the url ...huh?
Q:
How i can execute the controller class above, when im still on index.php?
I'm trying to figure out how to modify the .htaccess file so I can do two things:
Not have to include the .php extension on my PHP files (e.g., a request to my.domain.com/page maps to my.domain.com/page.php).
Do #1 while also including additional path info (e.g., a request to my.domain.com/page/path/stuff/here maps to my.domain.com/page.php/path/stuff/here).
I've found out how to do #1 by adding the following to the .htaccess file:
# Allow PHP files without ".php" extension.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)/?$ /$1.php [L,QSA]
However, now I'd like to modify the RewriteRule so it works for #2.
OK, after searching for MultiViews, I found several articles warning against them (eh, to each his own), but that also led me to an answer that uses 2 rules instead of just 1:
RewriteRule ^([^\.]+)$ /$1.php [L]
RewriteRule ^([^\./]+)/(.*) /$1.php/$2 [L]
The first rule catches case #1 above, and the second rule catches case #2 above. Voila!
You could just try to use Multiviews, which is made to do exactly this:
Options +Multiviews
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^([^\.]+)$ $1.php [NC,L] #Remove the .php
Not sure what you want with the pathing stuff though.
Edit based off your comment, I've used something like this with php/angular. It's probably not "correct" or the best way to do it, but it worked for me.
Htaccess
RewriteEngine on
# Allow the API to function as a Front Controller
RewriteRule ^api/(.*)$ api/index.php?rt=$1 [L,QSA,NC]
# Allow Angular to have Pretty URL's
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
api/index.php
// Pull the routing path
$router = explode('/', $_GET['rt']);
$version = $router[0];
$controller = $router[1];
$action = $router[2];
// Check for the file
if(file_exists($version . '/controllers/' . $controller .'.class.php')) {
include $version . '/controllers/' . $controller .'.class.php';
} else {
return false;
}
// Initialize and execute
$method = new $controller($action);
print $method->$action();
This lets me do something like: api/v1/users/login in the url, then will find the users.class.php file in the V1 folder, and run the function login.
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.
Ok so I have this site.... with the url
http://posnation.com/
and there are alot of pages that i need to save the url structure for....like this
http://posnation.com/restaurant_pos
http://posnation.com/quickservice_pos
http://dev.posnation.com/retail_pos
ext....
The problem that i have now is that i want to save the same url for all these pages and I am looking for the best approach. The way its working now is its done with a code in miva and we are getting off miva.... I know I can create a folder named restaurant_pos or whatever the url is and create an index.php in there.This approach will work but the problem is I need to do this for 600 different pages and I dont feel like creating 600 folders in the best approach.
any ideas
You should use .htaccess to route all the requests to a single file, say index.php and do the serving from there based on the requested URL.
The following .htaccess file on the server root will route all the requests to your index.php:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [L]
</IfModule>
Now you should parse the $_REQUEST['route'] to identify which file you should serve. Here is an example that will serve a page based on the last element of the URL (ex: pos):
<?php
$parts = explode($_REQUEST['route']);
if ($parts[count($parts) - 1] == 'pos') {
include "pages/pos.php";
}
Definitely you'll need to write your own logic, the above is just an example.
Hope this helps.
Usually the easiest way to do this is to create an .htaccess file that redirects all requests to /index.php. In /.index.php you analyze the URL using probably $_SERVER['REQUEST_URI'] and include the appropriate content.
Heres a sample htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
In your /.index.php do something like ... (this is just a VERY simple example)
require 'pages/' . $_SERVER['REQUEST_URI'] . '.php';
Now if someone goes to http://posnation.com/restaurant_pos pages/restaurant_pos.php will be included.
pages/restaurant_pos.php could include the header and footer too.
<?php require( HEADER_FILE ) ?>
restaurant_pos content
<?php require( FOOTER_FILE ) ?>