Environment bootstrapping with Titon\Environment
Handling multiple environments in an application can be tedious as each environment supplies its own set of configuration and unique bootstrapping. The amount of environments can grow to unmanageable numbers when dealing with dev environments, for example, different configuration for each developer. With no external dependencies, and a basic requirement of PHP 5.3, the Titon\Environment package hopes to solve this problem.
Defining Environments
An environment is mapped using an HTTP host or an IP address. During an HTTP request, an environment will be detected that matches the current host/IP, which is then loaded and bootstrapped. But first the environments need to be added through addHost(), which accepts a unique key, an array of hosts and IPs to match against, and finally the type. Out of the box, the package supports 3 types of environments — dev, staging and prod.
use Titon\Environment\Environment;
use Titon\Environment\Host;
// Create an environment instance
$env = new Environment();
// Register a dev env
$env->addHost(new Host('dev', array('127.0.0.1', '::1', 'localhost'), Environment::DEVELOPMENT));
What this did is create a development host environment for the localhost host, the 127.0.0.1 v4 IP, and the ::1 v6 IP. When either of those values are matched against the current request, the environment will be bootstrapped. But where does the bootstrapping take place? We must define it first! This can be accomplished through the setBootstrap() method on the Titon\Environment\Host object. Using the same example above, an absolute path to a bootstrap file can be defined.
$env->addHost(new Host('dev', array('127.0.0.1', '::1', 'localhost'), Environment::DEVELOPMENT))
->setBootstrap('/absolute/path/to/bootstrap.php');
Now when an environment is detected a bootstrap will occur. This bootstrap file should contain configuration and logic specific to each environment.
Multiple Environments
In the previous example only one environment was added, dev. In standard applications, at minimum 2 environments will exist, dev and prod. Let's add the prod environment through the production domain and include a fallback. A fallback is used when an environment cannot be matched — this usually will fallback to prod as there is no risk of dev code making it into production, or at minimum a dev environment with error reporting turned off.
$env->addHost(new Host('prod', 'website.com', Environment::PRODUCTION))->setBootstrap('/envs/prod.php');
// Set a fallback using the host key
$env->setFallback('prod');
Let's now solve the multiple developer issue mentioned in the opening paragraph.
// Share the default boostrap
$env->addHost(new Host('john', 'john.dev.website.com', Environment::DEVELOPMENT))->setBootstrap('/envs/dev.php');
$env->addHost(new Host('mike', 'mike.dev.website.com', Environment::DEVELOPMENT))->setBootstrap('/envs/dev.php');
// Custom boostrap
$env->addHost(new Host('chris', 'chris.dev.website.com', Environment::DEVELOPMENT))->setBootstrap('/envs/dev-chris.php');
Or perhaps multiple QA staging environments for different regions?
foreach (array('us', 'eu', 'cn', 'au') as $region) {
$env->addHost(new Host('qa-' . $region, $region. '.qa.website.com', Environment::STAGING))->setBootstrap('/envs/qa-' . $region. '.php');
}
Initializing An Environment
Once all the environment hosts have been defined, the package must be initialized. This can be done through the initialize() method, which will kick-start the matching and bootstrapping process.
$env->initialize();
Once an environment has been chosen, you can access it at anytime.
// Return the current host
$env->current();
// Or values from the host
$env->current()->getKey();
$env->current()->isStaging();
// Or use the convenience methods
$env->isDevelopment();
In Closing
For being such a lightweight class, the Titon\Environment package provides an extremely helpful application pattern. Be sure to give it a try in any MVC framework!