User friendly URLs without htaccess - php

I want to create friendly urls for my website script only using PHP, right now im using the query style (Ex: index.php?location=register) and i would like to convert them to something like this:
https://www.sitename.com/index.php/Register
Right now im using a $_GET based function to parse and include the php script based on the $_GET value.
$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);
}
Kind regards!

Okay, my comment keeps growing...so I guess I'll just provide an answer...
1) This still requires server configuration. In the case of Apache, I believe it's called MultiView. This is what allows Apache to look up a directory when the first path /file.php/somepage is not found...if you don't have the right configuration, it will just give a 404 error even though file.php exists. So, if your intention is to avoid the need for server configuration, it won't work.
2) What you are doing is dangerous:
$includeFile = basename(realpath($includeDir.$_GET['ajaxpage'].".php"));
All I have to do is know where some of your files are and I can potentially cause one of your PHP files to run...e.g. run your nightly cron every 5 minutes and overwhelm your server or some other page that might do some damage...you need some way of forcing only files with a certain name can be included...e.g.
$includeFile = basename(realpath($includeDir.$_GET['ajaxpage']."Controller.php"));
By forcing a suffix of Controller to the filename, you just have to make sure not to use the name Controller at the end of the file name for any file you don't want to be include-able.
3) There are so many MV* style frameworks out there...and there are so many security considerations, etc., that it is not always wise to create your own until you understand many or most of them. Even if you don't like them, using those frameworks will also help you learn some best practices for creating your own.
4) Finally, what in the world is the reason to avoid using URL Rewriting. URL Rewriting is the STANDARD for both Apache and Windows to create clean URLs. There is a reason that "everybody's doing it." If it's performance, your way will actually, probably, be slower because apache first has to look to see if the path exists, then go up a directory and see if that file exists, then go up another directory and see if that file exists until it hits a match...then open that file.

Why do you need to show index.php in the URL?
I would create my URL to look like this https://www.sitename.com/register if you truly want clean URL's but you would need to use something like the rewrite.
But you would need to use .htaccess or Apache config rules such as this.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?location=$1 [L]
Then in your PHP code you can do a get on location var $_GET["location"] and then load the page from the value sent.
The result of $_GET["location"] would be register from this URL and then you will display that page.
I don't suggest using MultiViews as it can cause issues if you have file and folders with the same name. e.g. /admin and admin.php.

Related

Show a 404 error when users access a directory on the server

I'm writing a small php site and I'm trying to structure it properly so that requests are handled centrally and there is a single point of entry to the code.
So I'm using the guide for a single entry point described here: https://thomashunter.name/blog/php-navigation-system-using-single-entry-point/
The mod_rewrite rule works well until you request a directory that actually exists on the server. I've disabled directory indexes but now the accesses behave differently depending on whether there is a trailing slash in the URL or not. With a slash, everything behaves the way I'd like (URL bar is www.example.com/images/ and the server returns a 404 created by my php script) but without a trailing slash the URL is rewritten to www.example.com/index.php?s=images which looks messy and exposes too much information about the structure of my site.
Seeing how it works with a trailing slash, ideally I want it to work the same way without the trailing slash. Otherwise, if it didn't work in any case, I'd settle for a simple redirect, although I don't like the idea of highlighting the real directories.
My .htaccess looks like this:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_]+)/?$ index.php?s=$1 [QSA]
Options -Indexes
ErrorDocument 403 index.php
I've also put in a header redirect but the ?s=images still gets appended to the URL (I am aware this can be written better but I'm experimenting with various combinations at the moment):
if (startsWith($_SERVER['REQUEST_URI'], "/main"))
{
header('Location: '.'/');
exit;
}
else if (startsWith($_SERVER['REQUEST_URI'], "/images"))
{
header('Location: '.'/');
exit;
}
where the definition of startsWith is (taken from this StackOverflow answer):
function startsWith($haystack, $needle)
{
return $needle === "" || strpos($haystack, $needle) === 0;
}
Finally, I'm looking for a solution that doesn't require copying dummy index.phps into every directory as that can get difficult to maintain. Any help or guidance will be appreciated.
you want some sort of routing, either via only apache Routing URLs in PHP or via one of the libraries (apache+php) that are avaliable
(like this one http://www.slimframework.com/)

php query without var=

I'd like the end user of my website to be able to do something along the lines of: example.com/user/user_name to show the statistics of that user on a different website. In short, I'd like to be able to make queries in php without having the user do: example.com/user/username=user_name I also have no way of knowing all of the possible users. I guess this means I'd like to always redirect to the index, while preserving the querystring that doesn't have "var=" in it. How would I do this?
you cna use the explode function in php. use it on the url slashes "/" and you get valid data to query. Remember to make it secure from sql injections.
EDIT
here you go:
$url = explode('/',$_SERVER['REQUEST_URI']);
echo 'user = '.$url[count($url)-1].'<br />
username = '.$url[count($url)-2];
EDIT 2
yeah you need to use .htaccess
unless you wanna get away with the questionmark
http://example.com?/user/username
EDIT 3
if you use apache you can make all traffic go through index.php with following .htaccess file:
RewriteEngine On
# always run through the indexfile
RewriteRule .$ index.php
Then if you want some folder to not go through to index.php, you add a htaccess file in that folder with:
RewriteEngine Off
The easiest way to do this is to still have the script be somepage.php?username=user_name and then have in your .httaccess file:
RewriteEngine On
RewriteRule ^/user/(.*) somepage.php?username=$1
This way you can still get the variable with $_GET['username'] but it looks nice to the user.

URL rewriting advice please

I would like to make my urls more seo friendly and for example change this:
http://www.chillisource.co.uk/product?&cat=Grocery&q=Daves%20Gourmet&page=1&prod=B0000DID5R&prodName=Daves_Insanity_Sauce
to something nice like this:
http://www.chillisource.co.uk/product/Daves_Gourmet/Daves_Insanity_Sauce
What is the best way of going about doing this? I've had a look at doing this with the htaccess file but this seems very complicated.
Thanks in advance
Ben Paton, there is in fact a very easy way out. CMSes like Wordpress tend to use it instead of messing around with regular expressions.
The .htaccess side
First of, you use an .htacess with the content below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Let me explain what it does (line by line):
if the apache module named mod_rewrite exists..
turn the module on
let it be known that we will rewrite anything starting after the
domain name (to only rewrite some directories, use RewriteBase
/subdir/)
if the requested path does not exist as a file...
and it doesn't even exist as a directory...
"redirect" request to the index.php file
close our module condition
The above is just a quick explanation. You don't really need it to use this.
What we did, is that we told Apache that all requests that would end up as 404s to pass them to the index.php file, where we can process the request manually.
The PHP side
On the PHP side, inside index.php, you simply have to parse the original URL. This URL is passed in the $_SERVER variable as $_SERVER['REDIRECT_URL'].
The best part, if there was no redirection, this variable is not set!
So, our code would end up like:
if ( isset( $_SERVER['REDIRECT_URL'] ) ) {
$url = explode('/', $_SERVER['REDIRECT_URL'] );
switch($url[0]){
case 'home': // eg: /home/
break;
case 'about': // eg: /about/
break;
case 'images': // eg: /images/
switch( $url[1] ){
case '2010': // eg: /images/2010/
break;
case '2011': // eg: /images/2011/
break;
}
break;
}
}
Easy Integration
I nearly forgot to mention this, but, thanks to the way it works, you can even end up not changing your existing code at all!
Less talk, more examples. Let's say your code looked like:
<?php
$page = get_page($_GET['id']);
echo '<h1>'. $page->title .'</h1>';
echo '<div>'. $page->content .'</div>';
?>
Which worked with urls like:
index.php?id=5
You can make it work with SEO URLs as well as keep it with your old system at the same time. Firstly, make sure the .htaccess contains the code I wrote in the one above.
Next, add the following code at the very start of your file:
if ( isset( $_SERVER['REDIRECT_URL'] ) ) {
$url = explode('/', $_SERVER['REDIRECT_URL'] );
$_GET['id'] = $url[0];
}
What are we doing here? Before going on two your own code, we are basically finding IDs and information from the old URL and feeding it to PHP's $_GET variable.
We are essentially fooling your code to think the request had those variables!
The only remaining hurdle to find all those pesky <a/> tags and replace their href accordingly, but that's a different story. :)
It's called a mod_rewrite, here is a tutorial:
http://www.workingwith.me.uk/articles/scripting/mod_rewrite
What about using the PATH_INFO environment variable?
$path=explode("/",getenv("PATH_INFO"));
echo($path[0]."; ".$path[1] /* ... */);
Will output
product; Daves_Gourmet; Daves_insanity_Sauce
The transition from using $_GET to using PATH_INFO environment is a good programming exercise. I think you cannot just do the task with configuration.
try some thing like this
RewriteRule ^/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+) /$1.php?id1=$2&id2=$3 [QSA]
then use $_GET to get the parameter values...
I'll have to add: in your original url, there's a 'prod' key, which seems to consist of an ID.
Make sure that, when switching to rewritten urls, you no longer solely depend upon a unique id, because that won't be visible in the url.
Now, you can use the ID to make a distinction between 2 products with the same name, but in case of rewriting urls and no longer requiring ID in the url, you need to make sure 1 product name can not be used multiple times for different products.
Likewise, I see the 'cat'-key not being present in the desired output url, same applies as described above.
Disregarding the above-described "problems", the rewrite should roughtly look like:
RewriteRule ^/product/(.*?)/(.*?)$ /product?&cat=Grocery&q=$1&page=1&prod=B0000DID5R&prodName=$2
The q & prodName will receive the underscored value, rather than %20, so also that will require some patching.
As you can see, I didn't touch the id & category, it'll be up to you to figure out how to handle that.

How to create dynamic/friendly URLs using PHP?

Can anyone explain how to create friendly URLs? I mean URLs like http://store.steampowered.com/app/22600/ that doesn't have any pages like index.php visible.
If you only have cpanel use .htaccess.
If that doesn't work, you are left with parsing the url in php with a link like this:
http://server.com/router.php/search
You can do that with something like this.
<?
list($junk,$url) = explode("router.php",$_SERVER['REQUEST_URI']);
$paths = explode("/", $url);
if ($paths[0] == 'search')
{
Header("Location: /search.php");
}
?>
http://articles.sitepoint.com/article/search-engine-friendly-urls
http://www.alistapart.com/articles/succeed/
Search revealed dozens more
You need to look up apache mod_rewrite (assuming you are using apache for your web server). PHP itself doesn't do it for you the web server does most of the work. You need to tell your web server to use mod_rewrite to point all urls that match a certain pattern to point to what ever .php file you like. You can pass arguments in your url pattern what ever way you choose. e.g. using the / to delimit key values or just values. If you don't have root access to the server and its enabled you can usually put these mod rewrite rules in a .htaccess file at the root of your site.
Sitepoint have a good reference for beginners.
http://articles.sitepoint.com/article/guide-url-rewriting
if you're using apache this should work/is the idea:
RewriteRule ^(.*)$ /index.php?/$1 [L]
now your url will go to http://store.steampowered.com/index.php/app/22600/

what is the best way to do that name?get=

ok assume i have php page
has this name name.php?get= and has get varible named get
ok
how i can make it appear like that name?get=
If you are using apache, mod_rewrite is one way to go. There is a whole bunch of mod_rewrite tricks here.
I'd seriously reconsider before using (or overusing) mod_rewrite.
In almost all of my projects I use a simple mod rewrite in the .htaccess:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*$ ./
AddHandler php5-script .php
This tells the server to forward all pages to / (index.php) unless a file otherwise exists.
In the root directory I have a folder called "views" with all of the pages that I use. E.g. the file used for /home would actually be /views/home.php. However, in the index.php I have a script that parses the user's url, checks for the file, and includes that.
$page = substr($_SERVER['REQUEST_URI'], 1);
if(!$page) :
header("Location: /home");
if(file_exists("views/$page.php")) :
include "views/$page.php";
else :
include "views/$page.php";
endif;
This creates a variable called $page that stores the value of everything in the URL after the domain name. I use a substr() function on the Request URI to get rid of the trailing forward slash (/) on the URL.
If the variable is empty, for example if the user is simply at http://example.com or http://example.com/ then it forwards them to /home, where the script then checks for the home.php file inside of the views folder. If that file exists, it includes it, and displays it to the user.
Else, the script will simply include the 404 page telling the user that the file doesn't exist.
Hopefully this helps you, and if you need any further explanation I'd be happy to help!
I think you're wanting to re-write the URL client-side, which would include mod_rewrite.
In the route of your website, create a file called .htaccess and place the following code in it:
RewriteEngine on
RewriteRule ^name?get=(.*) /name.php?get=$1
Now when you type http://www.example.com/name?get=something, it will actually map to http://www.example.com/name.php?get=something transparently for you.
As far as i could understand your question, you can not strip the file extension because otherwise it will not run. In other words, you can not change:
name.php?get=
into
name?get=
But if you mean to create links with query string values that you can put them in hyperlinks in this way:
Click here !!
If you're looking to create links using a variable '$get', then you can create the link like this:
<a href="name.php?get=$get>Link</a>
Or if you want to get the value of the query string variable, you can use this:
$get = $_GET['get']

Categories