views:

54

answers:

4

Hello.

As almost every programmer, I'm writing my own PHP framework for educational purposes. And now I'm looking at the problem with parsing URLs for MVC routing.

Framework will use friendly URLs everywhere. But the question is how to parse them in front controller. For example the link /foo/bar/aaa/bbb may mean "Call the controller's foo action bar and pass parameter aaa with value bbb. But in case someone installs a framework into the subdirectory of the domain root, the directory part should be stripped before determining controller name and action name. And I'm looking for a way to do it safely.

Also I would like to support a fallback case if URL rewriting is not supported on the server.

On different systems different sets of $_SERVER variables are defined. For example, on my local machine from the set of PATH_INFO, REQUEST_URI, REQUEST_URL, ORIG_REQUEST_URI, SCRIPT_NAME, PHP_SELF only REQUEST_URI, SCRIPT_NAME and PHP_SELF are defined. I wonder, if I can rely on them.

Mature frameworks like Symfony or ZF have some compicated algorithms of parsing URLs (at least it seemed to be so). So, I can't just take a part from there for mine.

A: 

Maybe you could take PHP_SELF and remove the first n chars where n is the length of SCRIPT_NAME.

Edit: Oops... seems like you can just take PHP_SELF: http://php.about.com/od/learnphp/qt/_SERVER_PHP.htm

thejh
On my home machine SCRIPT_NAME = PHP_SELF
FractalizeR
+2  A: 

Two workarounds:

  1. Add config variable with url / instalation directory to your application, and strip it from $_SERVER['REQUEST_URI']
  2. Make apache rewrite it to get variable

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule (.*) index.php?myrequest=$1 [QSA,L]
    
dev-null-dweller
Since many people use the faster Nginx server I would just go with PHP striping it out if you plan on sharing your framework.
Xeoncross
What about taking dirname of PHP_SELF and stripping it from the beginning of the REQUEST_URI? And does this have equivalent on nginx and IIS?
FractalizeR
I don't know about IIS, but it should also be possible in nginx. Taking only dirname of script will not be sufficient in many cases: symlinks, user directories (`server.com/~johndoe/` -> `/home/johndoe/www/`), more tahn one directory deep placement (`server.com/others/testit/yourapp`) and probably many more
dev-null-dweller
A: 

I'm currently doing the same research. But everything I see is so complicated that I'll most probably continue using mod_rewrite anyway. After all you end up with the same thing rather you use SEF with PHP or mod_rewrite with apache. Anyway I'll be monitoring this topic.. it's interesting :) Hope the php gurus around here have some more info about this :)

The Devil
What config of mod_rewrite do you use?
FractalizeR
The Devil
+1  A: 

I usually use the following for determining an application base URL path, assuming all your requests always goes through the same gateway script:

$base = dirname($_SERVER['PHP_SELF']);

For your second question, if you want to check if mod_rewrite is enabled, you can use:

if (in_array('mod_rewrite', apache_get_modules())) {
   // rewrite is enabled
}

However, it doesn't necessarily means that RewriteEngine is enabled, so you probably should use an extra condition:

if (in_array('mod_rewrite', apache_get_modules()) &&
    preg_match('/RewriteEngine +On/i', file_get_contents('/path/to/.htaccess'))) {
   // rewrite is enabled and active
}
netcoder
Will this also work on cases @dev-null-dweller pointed out in his comment?
FractalizeR
PHP_SELF contains the filename of the currently executing script relative to the document root, as per the web server config, not the filesystem. Symlinks and other stuff mentioned by @dev-null-dweller do not affect this.
netcoder