Handling multiple environments in raw PHP
Manuel
Posted on April 26, 2020
This post complements to these ones:
I can imagine you have at least 4 different environments in your app: one for developing, one for your CI, one for staging and one for production.
Let's see how we can handle them with ease.
In our case, if you come from previous posts, you know we are using PHP-DI. It's not completely necessary though, you can experiment with this solution depending on your app.
So we are going to have multiple config files outside src
folder named config
, in which there are going to be as many files as environments you have, for example:
ci.php
prod.php
dev.php
In which, let's say you need to specify your database credentials, so let's return something like this:
return [
'databaseConfig' => [
'driver' => 'mysql',
'host' => '127.0.0.1',
'username' => 'root',
'password' => 'toor',
'database' => 'database',
'port' => 3305,
],
];
And then we need to load it from several places, for example in our (previously explained) FixtureLoader
, for this we are going to use the following class:
class Config
{
private static array $config = [];
public static function getConfig()
{
if (!self::$config) {
$_SERVER['PHP_ENV'] ??= 'default'; // IN CASE YOU NEED A DEFAULT ENV
self::$config = include ("{$_SERVER['PHP_ENV']}.php");
}
return self::$config;
}
}
Where does this $_SERVER['PHP_ENV']
come from?
- In case you are running tests you can easily define it like PHP_ENV=e2e phpunit ...
- Web server configuration
For example nginx's configuration:
server {
...
fastcgi_param PHP_ENV env-desired;
...
}
This is quite practical since you can have multiple environments running at the same time, you just need as many web server configurations as environments you need running.
Then, you can configure your container:
$container = new DI\ContainerBuilder();
$container->useAutowiring(true);
$container->useAnnotations(false);
$container->addDefinitions([
Config::getConfig(),
DatabaseService::class => function (ContainerInterface $container) {
$databaseService = new DatabaseService($container->get('databaseConfig'));
$databaseService->connectToDb();
return $databaseService;
},
]);
if ($_SERVER['PHP_ENV'] == 'prod') {
$container->enableCompilation(__DIR__ . '/cache');
}
$container = $container->build();
As you see, whenever we get DatabaseService
from the container, it will get from its constructor the databaseConfig
we have set in the specified environment's file.
Posted on April 26, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.