Currently I have the following .htaccess file:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME}% !-d
RewriteCond %{REQUEST_FILENAME}% !-f
RewriteRule \.(js|css)$ - [L]
RewriteRule ^/?u/(.*?)/?$ /user-profile?user_id=$1 [L]
RewriteRule ^(.+)$ index.php [QSA,L]
It rewrites all files and directories to index.php, which does further routing, ignoring static js/css files.
With this line:
RewriteRule ^/?u/(.*?)/?$ /user-profile?user_id=$1 [L]
I am redirecting all requests to something like website.com/user-profile?user_id=timm to website.com/u/timm. I'm trying to figure out how to make it redirect to simply website.com/timm, but everything I have tried so far has given me a 500 error.
Here is the solution I ended up going with, if anyone ever finds themselves in a similar situation. It might not match up to anyone else's use case, but you never know.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME}% !-d
RewriteCond %{REQUEST_FILENAME}% !-f
RewriteRule \.(js|css)$ - [L]
RewriteRule ^/?edit-list/(.*?)/?$ /edit-list?list_id=$1 [L]
RewriteRule ^(.*)$ index.php?username-router=$1 [QSA,L]
My entire router looks like this:
// Routing
$redirect = $_SERVER['REDIRECT_URL'];
$method = $_SERVER['REQUEST_METHOD'];
// Get the path after the hostname
$path = ltrim($redirect, '/');
// Check if path matches a user
$username = $userControl->getUserByUsername(ltrim($path));
// Get controller name by converting URL of dashes
// (such as forgot-password) to uppercase class names
// (such as ForgotPassword) and assign to the proper
// controller based on URL.
$controllerName = getControllerName($redirect);
$controllerPath = $root . "/src/controllers/{$controllerName}.php";
// Load index page first
if ($controllerName === '') {
$controller = new Index($session, $userControl);
}
// If the controller exists, route to the proper controlller
elseif (file_exists($controllerPath)) { // to do: add approved filenames
$controller = new $controllerName($session, $userControl);
}
// If path matches user in the database, route to the public
// user profile.
elseif ($username) {
$controller = new UserProfile($session, $userControl);
}
// If all else fails, 404.
else {
$controller = new ExceptionNotFound($session, $userControl);
}
// Detect if method is GET or POST and route accordingly.
if ($method === 'POST') {
$controller->post();
} else {
$controller->get();
}
Related
I just started to learn htaccess and i'd like to rewrite my current urls from this:
http://www.url.com/?location=script
To:
http://www.url.com/script
So far i've managed to do this but now i want to have a directory with more controllers so i can have something like this:
http://www.url.com/script/method
Structure: Script directory --> method.php
Currently my directory structure for includes its like this:
assets-->client(directory):
login.php
logout.php
register.php
something.php
And i'd like to access these using a url like:
url.com/client/login
url.com/client/logout
url.com/client/register
url.com/client/something
My .htaccess:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?location=$1 [L]
</ifModule>
PHP based inclusion code:
####################################################################
# PARSE THE CURRENT PAGE #
####################################################################
$includeDir =".".DIRECTORY_SEPARATOR."assets/controllers".DIRECTORY_SEPARATOR;
$includeDefault = $includeDir."home.php";
if(isset($_GET['ajaxpage']) && !empty($_GET['ajaxpage'])){
$_GET['ajaxpage'] = str_replace("\0", '', $_GET['ajaxpage']);
$includeFile = basename(realpath($includeDir.$_GET['ajaxpage'].".php"));
$includePath = $includeDir.$includeFile;
if(!empty($includeFile) && file_exists($includePath)) {
include($includePath);
}
else{
include($includeDefault);
}
exit();
}
if(isset($_GET['location']) && !empty($_GET['location']))
{
$_GET['location'] = str_replace("\0", '', $_GET['location']);
$includeFile = basename(realpath($includeDir.$_GET['location'].".php"));
$includePath = $includeDir.$includeFile;
if(!empty($includeFile) && file_exists($includePath))
{
include($includePath);
}
else
{
include($includeDefault);
}
}
else
{
include($includeDefault);
}
All my controllers are in assets/controllers/ucp/login.php for example.
How about:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^(/client/[a-zA-Z0-9_\-]+)$
RewriteRule ^[a-z]+ index.php?location=$2 [L]
</ifModule>
It does include a leading slash and doesn't have the PHP extension. But this can be altered in PHP to suit your needs.
Be wary though, your code gives access to all your PHP files. You might want to check $_GET['location'] against an array of allowed locations. Consider the following URL as example of how this could go wrong
http://example.com/index.php?location=../drop_database.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 have been trying to do a htaccess URL rewrite (R=302) for a website which uses a $_get function to pull the content pages by use of strings. For instance, I am trying to change the following:
http://www.site.com/index.php?page=about
Into this:
http://www.site.com/about/
However, I have managed to get it set up to the point where it will redirect the header and footer data within the index.php file if I use query the second URL, but it will not grab the CSS or the $_get information for the content. Here are the htaccess entries and the $_get information:
RewriteEngine On
RewriteBase /
RewriteRule ^(.*?)/$ /index.php?page=$1 [NC,QSA,L]
RewriteRule ^(.*?)/$ $1.html [NC,L,QSA,R=302]
<?php
$folder = '';
$ext = 'html';
if (!$_GET['page'] || strpos($_GET['page'], '/') === true)
$path = 'home.' . $ext;
else $path = $_GET['page'] . '.' . $ext;
if (!file_exists($path)) {
$messages = array(
'404: Page does not exist; Please check the URL you entered.',
'404: Error 404, please check the URL of the page.'
);
print $messages[ rand(0, (count($messages) - 1)) ];
}
elseif (!#include($path)) print '300: couldn\'t get the page';
?>
Any help would be appreciated. I have been trying to modify the php code unsuccessfully thinking that is the issue.
First off, your two rewrite rules have the same condition, so only the first one will ever be met. I think you probably only want to rewrite if the requested uri doesn't exist on the server.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*?)/?$ /index.php?x=$1 [L]
I created a custom php MVC on windows and it worked great without any bugs but on linux I am facing some bugs like I am unable to access any other controller than my default one.
e.g: localhost/mymvc - This url redirects me to my default controller
but when I try to open any other controller e.g: localhost/mymvc/projects I get a "404 not found error"
Here are my functions that redirects:
/* ***** Getting URL ***** */
$url = isset($_GET['url']) ? $_GET['url'] : null;
$url = explode('/',$url);
/* ***** When URL does not contain any controller name call default controller ***** */
if(empty($url[0])){
$defaultpage = HOME;
require 'application/controllers/'.$defaultpage.'.php';
$controller = new $defaultpage();
$controller->loadModel($defaultpage);
$controller->index();
return false;
}
/* ***** When URL contains controller name ***** */
$page = 'application/controllers/'.$url['0'].'.php';
if(file_exists($page)){
require $page;
}else{
$this->error();
}
$controller = new $url[0];
$controller->loadModel($url[0]);
I am sure there are no bugs in here but still wanted you guys to review. I think have issues with .htaccess file so here is what I have in it:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
Undestanding your htaccess
Rewrite engine will be enabled:
RewriteEngine On
Base directory for rewrite will be /:
RewriteBase /
If request match a not existing file, continue:
RewriteCond %{REQUEST_FILENAME} !-f
If request match a not existing directory, continue:
RewriteCond %{REQUEST_FILENAME} !-d
If request match a not existing symbolic link, continue:
RewriteCond %{REQUEST_FILENAME} !-l
Rewrite to index.php:
// L means if the rule matches, don't process any more RewriteRules below this one.
// QSA Appends any query string from the original request URL to any query string created in the rewrite target
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
As we can see there is no actual problem with your htaccess.
Now you need to check if you have mod_rewrite enable in your apache.
You can just output phpinfo() and check if it's enabled.
Now into your PHP.
First be sure to remember that linux is case sensitive.
Debug:
After this line
$page = 'application/controllers/'.$url['0'].'.php';
Add this var_dump
var_dump($page);
Check if the path is correct and then do the rest of your debug analysis!
Regards
I've currently got a web application that I need optimizing, and one of methods or something I'm trying to achieve is such:
http://myweb/dept/app
from
http://myweb/?dept=dept&app=app
I've currently this as the PHP code for it:
if(empty($_REQUEST['dept'])) {
$folder = "apps/";
} else {
$folder = str_replace("/", "", $_REQUEST['dept']) . "/"; }
if(empty($_REQUEST['n'])) {
include('user/home.php');
} else {
$app = $_REQUEST['n'];
if(file_exists($folder.$app.".php")) {
include($folder.$app.".php");
} else {
include("global/error/404.php");
}
}
How do I do this?
I'm currently half there with:
RewriteRule ^([A-Za-z]+)$ /index.php?app=$1
but that only rewrites part of it.
Thanks
The way many frameworks do this is with one of the following rules:
RewriteRule ^(.*)$ /index.php?q=$1
RewriteRule ^(.*)$ /index.php
In the 1st case you get the query string in $_GET["q"].
In the 2nd case you have to get the query string from $_REQUEST or something. (just do some var_dumps till you find what you need).
Then you explode("/") this and you're all set.
Have a look at how TYPO3, eZPublish, Drupal do this.
You should also add the following conditions to allow the site to open your static files (like images/css/js/etc). They tell apache to not do the rewrite if the URL points to a location that actually matches a file, directoy or symlink. (You must do this before the RewriteRule directive)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
This should work:
RewriteRule ^([A-Za-z]+)/([A-Za-z]+)$ index.php?dept=$1&app=$2 [QSA]
You need the QSA part in order for any GET parameters to be appended to the rewritten URL.
You might find that it can be more flexible to rewrite everything to index.php, and then handle splitting up the url there, e.g.
.htaccess:
#only rewrite paths that don't exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
PHP:
<?php
$parts = explode('/', $_SERVER['PATH_INFO']);
$dept = isset($parts[0]) ? $parts[0] : 'someDefault';
$app = isset($parts[1]) ? $parts[1] : 'anotherDefault';