Setup clean URLs like CodeIgniter - php

I like the way CodeIgniter cleans URLs for sites, however, I have a site that is too involved to start over using the CI framework (at least for now), and I don't need the depth CI provides, I only have one level deep.
Is there an easy way to do this easily using straight PHP?
index.php?id=2454
index.php/2454/
NOTE: I need a straight PHP solution because the server is Windows and .htaccess is not setup to work.

If you use mod_rewrite in apache you can allow your application to dispatch requests as you want.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Say your server is located # http://coolguy.com and a users accesses http://coolguy.com/mycleanurl/
With the above rewrite rule in your .htaccess or apache configuration you can intercept which url is being accessed via $_SERVER['REDIRECT_URL'] and send it off to the specific code point you want.
The "RewriteCond" directives i have in there are used to ignore this rewrite rule if there exists a file directly at the location the user has specified, this is handy for static assets like CSS and images where you dont want to have to dispatch these requests yourself.

Check out $_SERVER['PATH_INFO'] - it returns anything trailing the script filename but preceding the query.
For example, in the URL:
http://www.domain.com/index.php/var1/var2
$_SERVER['PATH_INFO'] would contain /var1/var2
You could then write a function in your __construct() or init(), etc, to parse the path (e.g. explode("/", $_SERVER['PATH_INFO'])) and use the resulting array as variables.

Are you using Apache? If so, look into files called .htaccess. They rewrite the URL when they're stored in your directory. So if you put an .htaccess file in your web root with
# .htaccess
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/www/
RewriteRule ^(.*)$ /www/$1 [L]
then when a person goes to the URL yourdomain.com/page1, it will actually retrieve the resource yourdomain.com/www/page1 on your server, but their browser won't see the www.
So, for very simple URL rewriting you can use this to hide the ?var=val&var2=val2 crap in the URL
Information on the rules is here

If your using PHP on windows and want to do URL Rewriting you have two choices:
Url Rewrite (which allows you to use rewrite rules in the web.config) http://www.iis.net/download/urlrewrite - Open the site in IIS Manager and select "Url Rewriting", then add your rules.
Buy Helicon-APE or similar (which allows you to use a native .htaccess file) http://www.helicontech.com/ape/ - we use this on our shared windows hosting servers with great success

Related

How do I configure Apache (.htaccess?) to use mod_rewrite to pass virtual path to PHP file?

I have a script located at http://www.foo.bar/script and would like to use virtual path names to send data to that script. For example, http://www.foo.bar/script/this/is/a/path would pass "this/is/a/path" to /script. I would like to do this without changing the URL the user sees.
I've already gotten this to work with Apache mod_rewrite using something similar to what was suggested here htaccess mod_rewrite multiple paths to query string. What I have not been able to do is to pass the path to the script without changing the URL the users sees. So, a user that visits http://www.foo.bar/script/stackoverflow/rocks, the script residing at /script would receive /stackoverflow/rocks as a query string or URI but the URL would not change. I know this is not uncommon, and perhaps I'm using the wrong terminology when searching for an answer. Thank you for considering.
One idea someone suggested:
RewriteEngine On
RewriteBase /
RewriteRule "script/(.*)" "https://www.foo.bar/script/?data=$1" [R,L]
However, the above changes the URL in the browser. I don't want to expose "?" on the query string.
I don't really have the exact code you need but I have something I use that might just help you. The example above using rewrite_module will rewrite any URL with .php and will also accept the page name without the .php and redirect to a pageName.php witch is close to what you want, the name the users write, redirecting to the script you want. Additionaly it also offer some protection against cross scripting at the end of the URL.
<IfModule rewrite_module>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
RewriteCond %{QUERY_STRING} ^(.*?)(?:%3C|%3E|<|>)(.*)$
RewriteRule ^((.*)((?!([.]*p*h*p))\w+)) /$1?%1%2 [L,R=302,NE]
</IfModule>

Some header passing variable?

Im trying to pass some variables from the URL to the PHP script. Now I know that www.site.com/index.php?link=HELLO would require $_GET['link'] to get the variable "link". I was hoping there are other ways to do this without the variable.
For instance I want a link structure like this: www.site.com/HELLO. In this example I know that I have to create a Directory called Hello place an index file and it should work but I don't want to create a directory and Im hoping there's a way to "catch" that extra part after the domain. I'm thinking of creating a custom HTTP 404 Page that will somehow get the variable of the not found page, but I don't know how to get the HTTP 404 error parameters. Is there another simpler way to get a variable without the use of the extra ?link= part? I just want it to be a structure like this www.site.com/HELLO.
What you want is URL rewriting. You don't mention what kind of web server you're using, so I'll assume it's Apache.
If you have mod_rewrite enabled on your web server, this can easily be accomplished by creating a .htaccess file in your document root with the following
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?request=$1
This will make all requests - that match the regular expression [a-zA-Z0-9]+ - get forwarded to index.php. For instance, if you try to access domain.com/hello, PHP would interpret this as trying to access index.php?request=hello.
You can read more about this in the Apache HTTP Server manual about mod_rewrite.
In which case, you normally use .htaccess to alter the URL in some form. For instance:
RewriteEngine On #Enable Rewrite
RewriteCond %{REQUEST_FILENAME} !-f #If requested is not an existing file
RewriteCond %{REQUEST_FILENAME} !-d #If requested is not an existing directory
RewriteRule ^(.*)$ /index.php?link=$1 [L] #Preform Rewrite
Which will make www.site.com/hello to www.site.com/index.php?link=hello. This change is invisible to the user (he will still see www.site.com/hello as an address). Be advised that it may cause trouble if you try using relative paths with CSS/JavaScript files.
You need to use URL rewriting to do this. If you're using Apache: http://httpd.apache.org/docs/current/mod/mod_rewrite.html
you can do that with a mod-rewrite structure.
Here's a pretty good tutorial on how to set it up with php/apache.
http://www.sitepoint.com/guide-url-rewriting/

htaccess rewrite ".../pages/about.php" to ".../about"

I've searched and found a lot of questions on this site and elsewhere that are very similar, but I've tried implementing and modifying all the suggestions I've found and none of it works. I realize this is a very basic question an I am extremely frustrated because nothing I'm trying is working.
With that having been said... I am trying to organize my content pages within kurtiskronk.com/pages/... (e.g. kurtiskronk.com/pages/about.php)
What I want to do is make it so that I can simply link to kurtiskronk.com/about ... So how do I go about stripping "pages/" and ".php"? I don't have a ton of content pages, so it's not a big deal if I have to specify for each page, though something dynamic would be handy.
NOTES: I am using Rackspace Cloud hosting, and WordPress is installed in /blog. My phpinfo() can be seen at http://kurtiskronk.com/pages/phpinfo.php
This is my existing .htaccess file (in the root)
php_value register_globals "on"
Options +FollowSymLinks
RewriteEngine On
#301 redirect to domain without 'www.'
RewriteCond %{HTTP_HOST} ^www\.kurtiskronk\.com$ [NC]
RewriteRule ^(.*)$ http://kurtiskronk.com/$1 [R=301,NC]
RewriteBase /
RewriteCond %{ENV:PHP_DOCUMENT_ROOT}/pages/$1 -f
RewriteRule ^(.*)$ pages/$1 [L]
RewriteCond %{ENV:PHP_DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule ^(.*)$ pages/$1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ blog/index.php [L]
# PHP - MAIL
php_value mail.force_extra_parameters -kurtis#kurtiskronk.com
I tested and the rewrite works with the line below (/about as URL brings up file /pages/about.php), but then the homepage gives a 500 Internal Server Error:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pages/$1.php [L]
So I'm still sort of in the same boat as before, and as a follow-up, possibly more difficult question, if you go to http://kurtiskronk.com/weddings I am using SlideShowPro (flash) w/ SSP Director (self-hosted) as the back-end for it. When it pulls up a new image, it adds the following after /weddings ... "#id=album-152&num=content-9698"
There are four sections of the portfolio
# Homepage (kurtiskronk.com) id=album-148 ($id is constant for this section)
# Weddings (/weddings) id=album-152 ($id is constant for this section)
# Portraits (/portraits) id=album-151 ($id is constant for this section)
# Commercial (/commercial) id=album-150 ($id is constant for this section)
Assuming we get kurtiskronk.com/weddings to rewrite successfully without breaking anything, how would we make the total URL something cleaner kurtiskronk.com/weddings/9698 since the $num is the only thing that will change within a given section?
Kurtis, thanks for the extra information. It's a lot easier to give a specific answer to this.
My first comment is that you need to separate out in your thinking URI space -- that is what URIs you want your users to type into their browser -- and filesystem space -- what physical files you want to map to. Some of your mappings are URI->URI and some are URI->FS
For example you want to issue a permanent redirect of www.kurtiskronk.com/* to kurtiskronk.com/*. Assuming that you only server the base and www subdomains from this tree, then this cond/rule pair should come first, so that you can assume that all other rules only refer to kurtiskronk.com.
Next, you need to review the RewiteBase documentation. .htaccess files are processed in what Apache calls a Per-Directory context and this directive tells the rewrite engine what to assume as the URI base which got to this directory and .htaccess file. From what I gather, your blog is installed in docroot/blog (in the filesystem, and that you want to get to directory by typing in http://kurtiskronk.com/blog/ but that this .htaccess file is for the root folder -- that is the base should be (this goes before the www mapping rule)
DirectorySlash On
DirectoryIndex index.php
RewriteBase /
#301 redirect to domain without 'www.'
RewriteCond %{HTTP_HOST} ^www\.kurtiskronk\.com$ [NC]
RewriteRule ^(.*)$ http://kurtiskronk.com/$1 [R=301,NC]
You can add some field dumps look for REDIRECT_* in the Server or Environment table in the phpinfo O/P to see if these are sensible. For example:
RewriteWrite ^(.*)$ - \
[E=TESTDR:%{DOCUMENT_ROOT}/pages/$1.php,E=TESTPDR:%{DOCUMENT_ROOT}/pages/$1.php]
Your next rule is that if the file exists in the subdirectory pages then use it:
RewriteCond %{DOCUMENT_ROOT}/pages/$1 -f
RewriteRule ^(.*)$ pages/$1 [NS,L]
[Note that some shared service sites don't set up DOCUMENT_ROOT properly for the rewrite engine so you may need to run a variableinfo script (<?php phpinfo(INFO_ENVIRONMENT | INFO_VARIABLES); to see if it sets up alternatives. On your site you have to use %{ENV:PHP_DOCUMENT_ROOT} instead.]
Your next rule is that if the file exists, but with the extension .php in the subdirectory pages then use it:
RewriteCond %{DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule ^(.*)$ pages/$1.php [NS,L]
Now redirect any blog references to the blog subdirectory unless the URI maps to a real file (e.g. the blog stylesheets and your uploads.)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ blog/index.php [L]
A complication here is that WP may be using a poorly documented Apache feature call Path Info that is a script can act as a pseudo directory so http://kurtiskronk.com/blog/tag/downtown/ is redirected to docroot/blog/index.php/tag/downtown/ which is then executed by `docroot/blog/index.php using /tag/downtown/ as the PATH_INFO. But this is one for Wordpress experts to comment on. If this last rule doesn't work then try:
RewriteRule ^blog/(.*) blog/index.php/$1 [L]
PS. I like your site. I wish I was that young again :(
Postscript
When you say "it doesn't work", what doesn't with this .htaccess?
http://kurtiskronk.com/phpinfo,
http://kurtiskronk.com/phpinfo.php,
http://kurtiskronk.comblog/tag/downtown/
It's just that these rules work for these tests (with domain swapped) on mine. (One way is to move or copy the above variableinfo.php to the various subdirectories. If necessary temporarily rename the index.php to index.php.keep, say, and copy the variableinfo.php to the index.php file. You can now enter the various URI test patterns and see what is happening. Look for the REDIRECT_* fields in the phpinfo output, and the SCRIPT_NAME will tell you which is being executed. You can add more {E=...] flags to examine the various pattern results. (Remember that these only get assigned if the rule is a match.
Lastly note the changes above especially the additional NS flags. For some reason mod_rewrite was going directly into a subquery which was resulting in redirect: being dumped into the file pattern. I've had a look at the Apache code and this is a internal botch to flag that further redirection needs to take place (which then replaces this or backs out). However this open bug indicates that this backout can be missed in sub-queries and maybe that's what is happening here. Certainly adding the NS flas cured the problem on my test environment.
PS. Note the added explicit DirectoryIndex directive and also that whilst http://kurtiskronk.com will run the root index.php, the explicit /index.php version will run the one in pages, because that's what your rules say.
Here is a simple solution. You can use it apache conf file(s) or in .htaccess (easier to set up when you're trying).
mod_rewrite has to be enabled.
For example, use .htaccess in your DocumentRoot with:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pages/$1.php [L]
It will redirect /about to /pages/about.php, and any other page.
The "RewriteCond" part is to authorize access to an existing file (eg: if you had an "about" file at the root of your site, then it will be served, instead of redirecting to /pages/about.php).
Options +FollowSymLinks
RewriteEngine On
RewriteRule /([0-9]+)$ /pages/$1.php [L]
Put something like this in your .htaccess file. I guess that is what you want.
Juest a redirect from a simple url to a longer url.

how to use different url structure in php?

how to use different url structure in php ?
I want to know to handle url like this
www.example.com/10/2011
instead of
www.example.com/?m=10&y=2011
Maybe it will be better to do with server configuration - .htaccess (in Apache) or web.config (in IIS). Create rewrite rule from ^(\d+)/(\d+)$ to /?m=$1&y=$2. For example, in Apache it will look like:
RewriteEngine On
RewriteBase /
RewriteRule ^(\d+)/(\d+)$ /?m=$1&y=$2
this can be achieved through apache's mod_rewrite mechanism. create a .htaccess file in your webroot with the following contents:
RewriteEngine on
RewriteRule ^([0-9]+)/([0-9]+) ?m=$1&y=$2 [NC]
similar mechanisms exist for other web servers.
You should use Rewrite(google it) engine in Apache or nginx.
Something like this exists in ISS too.
This is not achieved by PHP, but by some other "component". E.g. the Apache web server has a module (the rewrite engine) that can rewrite the URL so that you can use URL like www.example.com/10/2011 and it translates them into www.example.com/?m=10&y=2011 so that in your PHP code you can use $_GET['m'] and get the month. Rewrite engine for Apache (for other webserver similar things may exist)
One easy method is something like this:
In your .htaccess file
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
What this does it redirects everyhting to index.php if its not a physical file or dir.
Then you configure your index.php to handle this request.
Example
www.example.com/10/2011
will become $_GET['10/2011'];
so you can use data in your script.

URL on apache server does not default to the .php file after / has been added

Generally a url that looks like this:
http://www.domain.com/product.php/12/
will open up product.php and serve the /12/ as request parameters, which then my PHP script can process to pull out the right product info. However when I migrated this whole site, after developing it, to a new server, I get a 404 error, because on that server it's not defaulting to the mother directory/file in case of an absence of requested directories.
I vaguely remember learning that this is generally a common apache function but I can't seem to recall how to set it up or how to manipulate it.. if there's an .htaccess method to achieve this that would be great.
What you're referring to is mod_rewrite. The official docs for it are here: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
You would configure it either in your VHost definition (recommended) or in an .htaccess file.
Assuming that you want to map all requests to a resource that Apache cannot serve (such as files that don't exist) to products.php you can use the following:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*)$ /products.php?request=$1 [NC,L]
You can then use $_GET['request'] to get the path requested and take it from there, depending on what you want to do. I'd normally recommend letting mod_rewrite handle parsing the request and passing the proper attributes to your PHP, but if you're not familiar with mod_rewrite it's probably easier to do it in your PHP.
you can use mod rewrite engine to map this to
http://www.domain.com/product.php?arg=12
Mod rewrite details: http://forum.modrewrite.com
Sample:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^files/([^/]+)/(.+) files.php?app=$1&file=$2 [NC]
this rewrite rule will map any request containing files/firstrPart/secondpart to the script files.php
everything between the first and second slash after files will be passed as parameter app and the rest as file
Basicly you define a regex with some subpaterns and state which script should really be called.
You cna refer to the subpatterns with $n where n is the 1 based index of the pattern.
Have fun.
NOTE this is a extreme simplification of mod rewrite. Please do some research before you use it because this might go terribly wrong...
The directive you're looking for is "AcceptPathInfo on". mod_negotiations MultiViews feature would also give you the option of not including the ".php" which is another common one people abuse mod_rewrite to do.

Categories