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.
Related
I would like to make the URLs of my Store URL-friendly.
Current URL Structure
https://my-domain.com/store/store.php?page=packages&id=1
Desired URL Structure
https://my-domain.com/store/packages/1
And also for direct access to the PHP files such as:
https://my-domain.com/store/profile.php to https://my-domain.com/store/profile
How would I need to go after this? I really appreciate any help you can provide.
Also might be note worthy that in the base directory a WordPress site is running with its own .htaccess file.
I already tried it with this
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^store/store/page/(.*)/id/(.*) /store/store.php?page=$1&id=$2
RewriteRule ^store/store/page/(.*)/id/(.*)/ /store/store.php?page=$1&id=$2
But that didn't work
This code will work.
RewriteEngine will remove .php from all PHP Files
RewriteRule will rewrite url like page/id
For Removing .php extension
RewriteEngine On
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]
For page/id
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)? store.php?page=$1&id=$2 [L]
</IfModule>
You can use this for the first part:
RewriteRule ^store/((?!store)[^/]+)/([^/]+)$ /store/store.php?page=$1&id=$2 [L]
Although nothing is wrong with anyone else's answers, the more modern way to do this (including WordPress, Symfony and Laravel) is to send non-existent URLs to a single router script. By doing this, you only have to mess with an htaccess file once to set things up, and never touch it again if you add more "sub-folders", you can do all of that in just PHP. This is also more portable which means you can bring it to other server platforms such as Nginx with little changes, and don't need to deal with RegEx.
The htaccess is fairly straightforward. Route all requests that start with /store/ and don't exist as a file (such as images, JS and CSS) or directory to a single new file called router.php in your /store/ folder. This is an internal redirect, which means it isn't a 301 or 302.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^store/ /store/router.php [L]
Then in your new router.php file you can parse $_SERVER['REQUEST_URI'] to determine the URL that was actually requested, and you can even rebuild the global $_GET variable:
// Parse the originally requested URL into parts
$requestUrlParts = parse_url($_SERVER['REQUEST_URI']);
// Parse the query string into parts, erase the old global _GET array
parse_str($requestUrlParts['query'], $_GET);
// Handle
switch($requestUrlParts['path']){
case '/store/store.php';
include '/store/store.php';
exit;
// Custom 404 logic here
default:
http_response_code(404);
echo 'The page you are looking for cannot be found';
exit;
}
I'd also recommend putting the htaccess rule into the site root's htaccess folder, above WordPress's. There's nothing wrong with creating multiple files, this just keeps things in a central place and makes it easier (IMHO) to debug.
This is the real url:
http://web/app/index.php?id=1
Here I have used current .htaccess and working fine with me.
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?id=$1
Now the url is : http://web.com/app/index/i and working fine
but here is the problem the real url
http://web.com/app/index.php?id=1&name=abc
How can I set mention url with .htaccess for keep it short or any other good solution for hiding URL-.
is it possible to show user only one url like , http://web.com/app but it could go to other pages while the url stay one url static.
If we say, good practice is to rewrite everything to one index page, like this:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
then in your index.php you get uri by $uri = $_SERVER['REQUEST_URI'] :
http://example.com/app -> $uri = /app
http://example.com/app/sub-app -> $uri = /app/sub-app
but also query string applies to the $uri variable:
http://example.com/app/?a=1&b=3 -> $uri = /app/?a=1&b=3
in this case, if you want to examine just uri part before ? question mark:
$realRri = strtok($uri,'?'); // and you have '/app/' instead of '/app/?a=1&b=3'
next you can examine and manipulate $uri;
Example:
$trimmedUri = trim($realRri, '/');
if ($trimmedUri == 'app')
{
// you can show app page
}
elseif ($trimmedUri == 'contact')
{
// show contact
}
else
{
// show 404 page not found
}
// you can have some dynamic also also
if (is_file($filePath = 'custom-page/'.$trimmedUri))
{
include $filePath;
}
else
{
// 404 page
}
Final Code (regarding your current script)
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
#rewrite php file
RewriteRule ^([a-zA-Z]+)$ $1.php
#rwwrite with id
RewriteRule ^([a-zA-Z]+)/([0-9]+)/?$ $1.php?id=$2
#rewrite with id and name
RewriteRule ^([a-zA-Z]+)/([0-9]+)/([0-9a-zA-Z]+)/?$ $1.php?id=$2&name=$3
I think what you're looking for is something like AJAX, mostly because of
but it could go to other pages while the url stay one url static.
in which case, you would looking at JavaScript and not php. You would need a way to quickly deal with the data and change it how you want it. I've recently started learning Angular, and it shows a lot of promise. Go through the tutorial yourself (just google angular.js and the tutorial is on their website), or some other JavaScript library (unless you want to hard-code everything, in which case, good luck) like jQuery or MooTools (names mentioned because they're libraries i have knowledge with). To my knowledge (I am no code guru) but a website's URI is what tells the server what to show you. You can make shortcuts
If, however, you want for it to just not have the .php filename, then I believe that
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)\.php\??(.*)$ $1.php&$2
Should, theoretically get you what you want.
Note: I can't test it right now, so it may error out.
EDIT: It does error out.
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 have a webcommunity, and it's growing now. I like to do a link makeover for my web, and then I need to know the best solution for my case.
Right now my htaccess looks kind of like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ index.php?page=user&username=$1 [L]
You are able to link to users like this domain.com/username and that's nice.
Then I have different pages like
index.php?page=forum&id=1
index.php?page=someotherpage&id=1&anotherid=5
index.php?page=3rd
... and so on. I want them to look something like this:
domain.com/forum/23/title-of-the-thread
domain.com/page2/id1/id2
... and so on.
How do I make these pretty urls without removing my domain.com/username functionality? What solution would you suggest?
I was thinking about creating a file that checks the URL, if it matches any pages, and users and so on. Then it will redirect with a header location.
If all of the urls you are going to rewrite are going to the same end point, you could simply use:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
in index.php:
<?php
$url = $_SERVER['REQUEST_URI'];
How you use the request uri is up to you, you could for example use a simple strpos check:
<?php
$url = $_SERVER['REQUEST_URI'];
$rules = array(
'/forum/' => 'forum',
'/foo/' => 'foo',
'/' => 'username'
);
foreach($rules as $pattern => $action) {
if (strpos($url, $pattern) === 0) {
// use action
$file = "app/$action.php";
require $file;
exit;
}
}
// error handling - 404 no route found
I was thinking about creating a file that checks the URL,
you actually have that file, it's index.php
if it matches any pages, and users and so on. Then it will redirect with a header location.
that's wrong. HTTP redirect won't make your URLs look "pretty"
you have to include appropriate file, not redirect to.
Just change your rule to more general one
RewriteRule ^(.*)$ index.php [L,QSA]
You basically have two options.
Route all URLs to a central dispatcher (FrontController) and have that PHP script anaylze the URL and include the correct scripts
Note every possible route (url rewrite) you have in the .htaccess
I've always worked with option 1, as this allows greatest flexibility with lowest mod_rewrite overhead. Option 2 may look something like:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^forum/([^/]+)/([^/]+)/?$ index.php?page=forum&id=$1 [L]
RewriteRule ^otherpage/([^/]+)/([^/]+)/?$ index.php?page=someotherpage&id=$1&anotherid=$21 [L]
RewriteRule ^page/([^/]+)/?$ index.php?page=$1 [L]
# …
RewriteRule ^([^/\.]+)/?$ index.php?page=user&username=$1 [L]
you said
I was thinking about creating a file that checks the URL, if it
matches any pages, and users and so on. Then it will redirect with a
header location.
While "creating a file that checks the URL" sounds a lot like option 1, "redirect with a header location" is the worst you could do. That would result in
an extra HTTP roundtrip for the client, leading to slower page loads
the "pretty URL" won't stick, the browser will show the URL you've redirected to
losing link-juice (SEO)
This can be done entirely with htaccess or php
//First Parameer
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?page=$1
RewriteRule ^([a-zA-Z0-9_-]+)/$ index.php?page=$1
//Second Parameter
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)/([0-9]+)$ index.php?page=$1&username=$2
RewriteRule ^([a-zA-Z0-9_-]+)/([0-9]+)/$ index.php?page=$1&username=$2
read more about it here:
http://net.tutsplus.com/tutorials/other/using-htaccess-files-for-pretty-urls/
http://www.roscripts.com/Pretty_URLs_-_a_guide_to_URL_rewriting-168.html
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';