Handling multiple environments in raw PHP
Tags: php, e2e, deployment
Published: 2020-04-26 18:57:31

---
title: Handling multiple environments in raw PHP
published: true
description: Tutorial for managing several environments in raw PHP
tags: PHP, E2E, Deployment
cover_image: https://miro.medium.com/max/1382/1*vgTcI3lm42opXs6QxqL7fw.png
---

This post complements to these ones:

- [Handmade E2E in raw PHP](https://dev.to/manuelmolina97/handmade-e2e-in-raw-php-4lel)
- [Managing fixtures in raw PHP](https://dev.to/manuelmolina97/managing-fixtures-in-raw-php-56i0)

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](http://php-di.org/). 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:

```php
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:

```php
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:

```php
$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.