-1

Currently I let a single PHP script handle all incoming URLs. This PHP script then parses the URL and loads the specific handler for that URL. Like this:

if(URI === "/")
{
    require_once("root.php");
}
else if(URI === "/shop")
{
    require_once("shop.php");
}
else if(URI === "/contact")
{
    require_once("contact.php");
}

...

else
{
    require_once("404.php");
}

Now, I keep thinking that this is actually highly inefficient and is going to need a lot of unnecessary processing power once my site is being visited more often. So I thought, why not do it within Apache with mod_rewrite and let Apache directly load the PHP script:

RewriteRule ^$ root.php [L]
RewriteRule ^shop$ shop.php [L]
...

However, because I have a lot of those URLs, I only want to make the change if it really is worth it.

So, here's my question: What option is better (efficiency-wise and otherwise) and why?

Btw, I absolutely want to keep the URL scheme and not simply let the scripts accessible via their actual file name (something.php).

unicornop
  • 79
  • 6
  • How are you dealing with static resources like style sheets and images? As long as those don't get passed through the PHP script, it's probably okay – Pekka Aug 05 '11 at 19:22
  • @Pekka, well they are, because some resources are only available to logged in users, so I get to check cookies and login state first, then I serve them with readfile(). But thank you for actually providing the first real answer to my problem. – unicornop Aug 05 '11 at 19:37
  • by the way you should be using `switch - case` – Ujjwal Singh Dec 30 '12 at 20:47

4 Answers4

0
RewriteRule ^([a-z]+)$ $1.php [L]

and rename root.php to index.php.

Nikola K.
  • 7,093
  • 13
  • 31
  • 39
Jacek Kaniuk
  • 5,229
  • 26
  • 28
  • it wouldn't - [a-z]+ would not match dot in it – Jacek Kaniuk Aug 05 '11 at 19:22
  • Next time, it'd be really nice if you actually **read** the question. This isn't an answer. And your single line won't work in my case because I use dynamic URLs like /item/2839/page3. The examples I provided are just a stripped down version of what I am doing, stripped of all unnecessary noise for this question. – unicornop Aug 05 '11 at 19:24
  • right, my bad, but it won't catch foo-bar, foo_bar or similarities either. – Madara's Ghost Aug 05 '11 at 19:24
  • 3
    @unicornop - just modify regexp to match all URLs. we are not phophets to know how they look like – Jacek Kaniuk Aug 05 '11 at 19:25
  • you don't need to be a prophet to read my question, to which you haven't provided any answer. – unicornop Aug 05 '11 at 19:33
  • there is nothing in your question related to that. if it is - name it – Jacek Kaniuk Aug 05 '11 at 19:34
  • I quote from a few lines above: _So, here's my question: What option is better (efficiency-wise and otherwise) and why?_ I haven't asked you to code my .htaccess file for me. I just want to know which of the two ways to handle URIs (through one PHP script, or through mod_rewrite) is better and why. Your original answer, which only provided one line with a RewriteRule hasn't answered that question. – unicornop Aug 05 '11 at 19:38
  • @unicorn you have to admit though that your question isn't 100% perfect either. For example, the information that you are passing static resources through this front controller as well is vital, and should have been there in the first place – Pekka Aug 05 '11 at 19:50
  • Well, I say that right in the first sentence: _Currently I let a **single** PHP script handle **all** incoming URLs._ – unicornop Aug 05 '11 at 19:54
  • @unicorn fair enough, although more emphasis ("*including* images etc.") wouldn't hurt. Anyway, it's clear now – Pekka Aug 05 '11 at 20:00
0

The PHP approach is correct but it could use a bit of improvement.

$file = $uri.".php";
if (!is_file($file)) { header("Status: 404 Not Found"); require_once(404.php); die(); }
require_once($uri.".php");
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • Won't work for the same reasons I explained in comment #3 to Jacek_FH's answer. Again, the example URIs I provided aren't what I'm using, but that shouldn't be a problem if someone actually read the question. – unicornop Aug 05 '11 at 19:34
  • I've read your question thoroughly and I fail to see where my answer is not sufficient. If you think you oversimplified your question, why don't you post a more actual example of your code? – Madara's Ghost Aug 05 '11 at 19:40
  • So, how would I handle /items/34893/page3 with your code? I can with mine (e.g. using an if statement with substr(URI, 0, 7) === '/items/' or preg_match). – unicornop Aug 05 '11 at 19:43
  • And two different URLs might actually use the same handler, e.g. /items and /cheap-items/ – unicornop Aug 05 '11 at 19:45
  • Well, in that case my code will include "items/34893/page3.php", which does not contradicts anything you've asked in your question, again, please elaborate if there are any further rules for it. As for your original question, I think PHP would be better then using ModRewrite on this one. – Madara's Ghost Aug 05 '11 at 19:50
  • _As for your original question, I think PHP would be better then using ModRewrite on this one._ OK. Why? – unicornop Aug 05 '11 at 20:03
  • It's a point of view really. I generally dislike using ModRewrite, and PHP seems to be able to do it rather easily. I think ModRewrite should only be used in some VERY general cases. – Madara's Ghost Aug 05 '11 at 20:11
0

OK, as for efficiency - htaccess version with regexp and php version with single regexp and loading of matching file would be faster than many htaccess rules or many php if - else

Apart from that, htaccess and php way should be similar in efficiency in that case, probably with little gain with htaccess (eliminating one require in php)

Jacek Kaniuk
  • 5,229
  • 26
  • 28
  • 1
    I disagree with your last sentence. With PHP, a complete instance has to be started, memory reserved, sessions started, etc. It can become quite a resource hog if not used carefully. Where sensible, it's best to use Apache's logic. – Pekka Aug 05 '11 at 19:46
  • but php will be loaded at the end after all - it's one php load in both cases – Jacek Kaniuk Aug 05 '11 at 19:47
  • not necessarily if the requested resource is a static one. (Other than that, you're correct.) – Pekka Aug 05 '11 at 19:49
0

So, here's my question: What option is better (efficiency-wise and otherwise) and why?

If every resource has to run through a PHP based check, as you say in your comment:

some resources are only available to logged in users, so I get to check cookies and login state first, then I serve them with readfile().

then you can indeed use PHP-side logic to handle things: A PHP instance is going to be started anyway, which renders the performance improvement of parsing URLs in Apache largely moot.

If you have static resources that do not need any session or other PHP-side check, you should absolutely handle the routing in the .htaccess file if possible, because you avoid starting a separate PHP process for every resource. But in your case, that won't apply.

Some ideas to increase performance:

  • consider whether really every resource needs to be protected through PHP-based authentication. Can style sheets or some images not be public, saving the performance-intensive PHP process?

  • try minifying resources into as few files as possible, e.g. by minifying all style sheets into one, and using CSS sprites to reduce the number of images.

  • I've heard that nginx is better prepared to handle this specific kind of scenario - at least I'm told it can very efficiently handle the delivery of a file after the authentication check has been done, instead of having to rely on PHP's readfile().

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • @unicorn no problem. I asked a very similar question once: [Performance-oriented way to protect files on PHP level?](http://stackoverflow.com/q/1688568) the answers suggest that there is no really *good* way to solve this - if you want performance, you have to expose your resources to the public, if you want security, you have to run the request through a PHP check every time – Pekka Aug 05 '11 at 20:07