The bootstrap: Germination of your application

Sunflower seedlings

Sunflower seedlings

After the start of your (PHP) application it will grow. You will include more and more files, execute more functions and handle more data. When you are finished processing, all memory will be released and your app will ‘die’. Summarized you could represent your application as something simple like a plant!

The first part of “it’s life” is germination, your application has to start and set up everything he needs. In more technical terms you can call this term the bootstrap. If you use a framework such as Zend Framework you’ve probably already heard from it. Using a .htacess file you direct all traffic to your bootstrap that then will startup the main application. For a person like I (who creates PHP CLI apps) the bootstrap is a way of setting important environment variables. So what should a bootstrap do? In my view the most important tasks are:

  1. Setting application environment
  2. Configuring the PHP environment
  3. Configuring autoloading
  4. Loading configurations
  5. Starting the main application

I doesn’t seem like much but if you use them properly a bootstrap can be really helpfull. Moreover, if you (like me) only program using objects (OOP) you need a file that starts your main class so you need a bootstrap anyway.

Now I want to further explain these 5 components of the bootstrap using a live example: the bootstrap of Mai Ocean. I will try to keep it as general as possible so I won’t use a framework. Of course I only give my view, the best bootstrap is the one that fits you and your app so after reading this post go create your own and share it if you like! :)

1. Setting application environment

let’s start with the first part: the application environment. For all my applications I start with some ‘application constants‘. I use these to define global information about the application. For example, Mai Ocean has the following constants:

define('APP_NAME',		'Mai Ocean');
define('APP_VERSION',		'0.1.0trunk');
define('APP_STAGE',		'development');

Because they all start with the prefix “APP” I can easily identify and use them throughout the application. The first two I only use for informational purposses and are not needed for the application. For example: bots created with Mai Ocean show the name and the version of the application in their private message. The third constant (APP_STAGE) is the most important and is actually used. I split config files in multiple sections and this constant defines what section should be loaded (in this case the development section). You may think: “This is pretty simple..” and you are absolutely right but constants like these can be really useful.

Because I use autoloading I have to define paths to my models, controllers and other classes to make it work. These paths are part of my application so I define them (just like the application constants) with constants. Due to this I can always use a constant if I want to use a path, then when I want to move something I only have to change the constant. For Mai Ocean I use the following:

define('PATH_ROOT',		__DIR__);
define('PATH_LIBRARY',		__DIR__.'/library');
define('PATH_EZCOMPONENTS',	__DIR__.'/library/eZComponents');
define('PATH_APPLICATION',	__DIR__.'/application');
define('PATH_CONTROLLERS',	__DIR__.'/application/controllers');
define('PATH_MODELS',		__DIR__.'/application/models');
define('PATH_HANDLERS',		__DIR__.'/application/handlers');

After this I can set my include path. As you might already know, the order of your include path is important because they are searched. PHP will search them in the order you’ve set them so set the most important directories first. I usually start with my application and models dir because it contains the most files I use:

set_include_path(
	PATH_APPLICATION 	. PATH_SEPARATOR .
	PATH_MODELS		. PATH_SEPARATOR .
	PATH_LIBRARY		. PATH_SEPARATOR .
	PATH_EZCOMPONENTS	. PATH_SEPARATOR .
	PATH_HANDLERS		. PATH_SEPARATOR .	
	get_include_path()
);

2. Tweaking the PHP environment

The first part was pretty simple so lets continue. PHP has a large config file (php.ini) and especially when you write applications that will be used on multiple installations you should not trust them. If you rely on some config values you should set them yourself. The best place for that is (you could have guessed it) your bootstrap!

Probably the most important settings you should configure are the error settings. Of course you can change these with error_reporting() but I like to use ini_set() instead. When developing you want to show errors on screen, this is easier than reading a log when something goes wrong. Nevertheless, when you are ready for production you do not want to show errors any more. Instead of displaying them on screen you can easily save them to a log file. You could also create a custom error handler that would send an email to you or something like that. Anyway to set the error settings you could use the following:

ini_set('display_errors', 	0); //Do not display errors on screen
ini_set('error_reporting', 	E_ALL | E_NOTICE | E_STRICT); //Show ALL errors
ini_set('log_errors', 		1); //Log errors
ini_set('error_log', 		PATH_ROOT . '/log/error.log'); //Path of the error log

Some other settings I use often are memory_limit (to handle a lot of data) and max_execution_time (to enable scripts that run forever). All settings you can set can be found at the PHP Manual: http://php.net/manual/en/ini.list.php.

Besides errors I also always configure assertions are handled. I use them a lot and configuring them makes them even more useful. I’d already written down some of the possible configuration in my post about assertions (Assertions, protection against yourself) but wrote down my full configuration list below:

assert_options(ASSERT_ACTIVE, 		1); //Enable assertions
assert_options(ASSERT_BAIL,			1); //Terminate execution on failed assertions
assert_options(ASSERT_WARNING,		1); //Issue a PHP warning for each failed assertion
assert_options(ASSERT_QUIET_EVAL,	0); //Do not disable error_reporting during assertion expression evaluation
assert_options(ASSERT_CALLBACK,		'someFunction'); //Some function to handle assertions (don't have one yet)

This configuration I use when developing because I want to see when an assertion fails. On production I would disable warnings and let my callback handle the error.

Now there is only one thing left we need to configure. When you use date/time functions you may have already have seen this:

Note: Since PHP 5.1.0 (when the date/time functions were rewritten), every call to a date/time function will generate a E_NOTICE if the timezone isn’t valid, and/or a E_WARNING message if using the system settings or the TZ environment variable.

So we have to set a valid timezone, this is really easy. Just add the following to your bootstrap:

date_default_timezone_set('Europe/Amsterdam');

3. Configuring autoloading

I can be short at this: autoloading is great! :D I am not going to explain how autoloading works because it is pretty straightforward. I use Zend_Loader_Autoloader as a base who uses the autoloader of eZ Components and also my own autoloading algorithm. In my bootstrap I only have to do the following:

//Get the Mai Ocean autoloader
require_once('Autoloader.php');
//Create a new autoloader for this application
$autoloader = new MaiOcean\Autoloader;

4. Loading configurations

My controllers, models and other objects use configurations who I store in ini-files. These files are loaded and parsed in my bootstrap because I do not want to define them into my objects. Also, (unit) testing will be a lot easier if you can insert custom configurations.
My favourite method is creating a config creator object that combines multiple ini-files in one Zend_Config object.

//Create a config object to load all config files
$config = new MaiOcean\Models\Config;
 
$config->addModule('application/default');
$config->addModule('users/development');
 
$config = $config->createConfig();

In the example above I load 2 ini-files: the default configurations and the development user data. The last line will return a new Zend_Config object that contains all my configurations.

5. Starting the main application

You may have noticed but we have reached the last part: starting the main application. This is important but also the easiest part. If you use a framework you will probably dispatch a front controller. In my case (a CLI application) I just start up the main controller:

//Create and run the controller for the Mai Ocean application
$controller = new MaiOcean\Controller\MaiOcean($config);
 
$controller->run();

The end..?

We have reached the end of the bootstrap and of my article. I hope you’ve learnt something about my way of creating bootstraps. I’m very curious about your ideas so let me know! The full bootstrap of Mai Ocean can be found at launchpad.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Hyves
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • PDF
  • Reddit
  • StumbleUpon
  • Technorati
  • Twitter
  • Add to favorites
  • NuJIJ
  • RSS

Tags: , , , , , , , , , , , , ,

Leave a comment