views:

1432

answers:

5

Is it a good practice to bootstrap your PHP application. I found two ways to bootstrap my PHP application. Need some suggestions which is a better way.

First.
Define a constant for the folder structures

$controllerPath = 'controller';
define('CONTROLLER', str_replace('\\', '/', realpath($controllerPath)).'/');

//usage
require_once CONTROLLER . 'somecontroller.php';

Second
Using ini_set set the include path to the application root

$rootPath = $_SERVER['DOCUMENT_ROOT'];
$includePath = ini_get('include_path');
ini_set('include_path', '.'.PATH_SEPARATOR.$rootPath.PATH_SEPARATOR.$includePath);

//usage
require_once 'controller/somecontroller.php';

Please tell me which is a better way.

In case of a high-load application which would be the best method ??

+3  A: 

Use ini_set to set it to the directory -above- your application. That why you can use the literal strings in your require statements. In addition, it makes it easier to use reuse code

require 'coolapp/class/Model.php'
require 'coolapp/display/Router.php'
require 'spinoff/display/JsView.php'
// etc

Its similar to the idea in java of having fully qualified imports of com.whatever.app.more, or how in python all of an apps imports should be absolute with respect to that app.

Re: High load application

Unless you are loading many thousand files, the time it takes to include files probably isn't a bottle neck. But, if it was the case you have a couple options. One is APC, which caches the results of include in memory. Another is to load everything from a single file, similar to how javascript files are concatenated into one for better performance (coincidentally, APC has a function that gives you this information). APC is really easy to setup and is completely transparent, for a boost of ~50% better performance.

Richard Levasseur
A: 

Better use absolute paths than letting PHP find the file in one of the given include paths.

So I tend for the first way using a constant that holds the absolute path to the application root.

Gumbo
A: 

I much prefer the second way - used it on a large PHP project and enjoyed it very much.

Ray Hidayat
A: 

This is what I do:

  • Put an /include directory at the top of your document root (or whatever you want to call it) for all classes, helper functions and so on;
  • Make it so the /include directory isn't served by using mod_rewrite;
  • Have a file in there called, say, setup.php, which sets up relevant ini parameters, paths, etc;
  • Thhat file is included in every page by relative path; and
  • Everything else can then rely on the settings it has created.

Example rewrite rules for top-level .htaccess:

RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /include/
RewriteRule ^include/ - [R=404,L]

I might be off slightly. I don't have my standard rules handy. You'll note that it's a 404 error I create rather than 403 (Forbidden). That's deliberate. When you login to a system it doesn't say "unknown user" or "password incorrect" because that tells you something. I'd rather pretend there was no /include directory at all rather than say it's there but you just can't look at it.

At that point you can setup all you need so the rest of your code can just do:

require 'Class.php';

or even define an __autoload() so it happens automatically.

cletus
+1  A: 

Here's an example of my bootstrap loader:

if (!defined('APPLICATION_PATH')) {
    define('APPLICATION_PATH', realpath(getcwd() . '/../application'));
}

/**
 * Add the APPLICATION_PATH and the library dir to the include_path
 */
set_include_path(get_include_path() . PATH_SEPARATOR . APPLICATION_PATH . PATH_SEPARATOR . realpath(APPLICATION_PATH . '/../library'));

/**
 * Load the file loader to setup the class autoloader
 */
include_once 'Loader.php';
if (!class_exists('Loader')) {
    die('Could not load class loader.');
}

spl_autoload_register('Loader::autoload');

I'd personally go with the second way. I've learned to love the include_path: there is probably some performance hit from looking in lots of directories but I doubt it would be significant. It also prevents errors from forgetting to include the path constant.

On a side note I put my controllers, etc. in /application/, and have some libraries in /library/. This all goes above the web root. It fully prevents users from accessing these files, which you have to otherwise take precautions against if you have everything under the document root. If your host supports this (some shared hosts don't) take advantage of it!

Update

In case of a high-load application is it good to go with the second method ??

In my opinion if you were to keep an eye on what's in your include_path (for example, on my Windows dev machine I have all sorts in there that I don't need: SQL Server, Ruby etc.) and were to strip out anything not needed then the second method would be fine.

Another thing you could do is dump the include_path at the end of the script and hard code it into your php.ini file.

Really, though. I don't think this is going to be a bottleneck in your system performance. Use what's easier for you.

Do you have performance issues on a site you're running or is this precautionary stuff? I can see why you'd want to preoptimise (I have to stop myself from doing it) but seriously. Deal with those issues when they arise. When you're in the lucky position of having a popular site deal with it then. At the end of the day, it's not a nightmare if you have to replace a few requires.

Ross
Autoload is a good thing to do.
Mark Davidson
Yes, that's another thing: if you're on PHP5 (which you should be) autoloading classes (no requires, just instantiate the class) is an incredibly useful tool. http://www.php.net/autoload
Ross
Its a precautionary stuff. But the application is a big one, so I dont have just a few 'require_one' so it will be a nightmare for me :)
Undefined
I'd advise you to look at autoload anyway. It means that classes are loaded as they are used. You might have to use some naming conventions but I usually use a directory structure. E.g. Zend_Form = Zend/Form.php
Ross