DEV Community

Cover image for Building deploy ready PHP apps
Sadick
Sadick

Posted on • Updated on

Building deploy ready PHP apps

What does deploy ready even mean.
It means that your application should be able to be deployed in any environment without changing the application code.

To make sure your application is deploy ready, things that can change between deploys(staging, alpha or production) should not be hard coded in your app.

I know you have come across or even written code like the one below while trying to make a database connection.

class Database
{
    public function connect($host, $user, $password)
    {
        $pdo = new PDO("mysql:host=$host;dbname=myDB", $user, $password);
        return $pdo;
    }
}

$db = new Database();
$db->connect("localhost", "root", "password");
Enter fullscreen mode Exit fullscreen mode

There are two things wrong with the above approach:

  • You are hard-coding and exposing your database login credentials, which is just insecure
  • When you deploy your app to other environments you have to edit the connection code so that connection doesn't fail (unless that environment has the exact config)

To remedy the above code, you need a way to supply the credentials without hard coding them. This is achievable by using environment variables.
An environment variable is a dynamic-named value that can affect the way running processes will behave on a computer. In your case the dynamic value would be database username, address, password

Setting the environment variables

If you own the server you will be deploying to you can set the environment variables as below.

On windows server

setx DB_NAME test
setx DB_HOST localhost
setx DB_PASSWORD password

Enter fullscreen mode Exit fullscreen mode

On ubuntu server

  • Open a terminal (by pressing CtrlAltT)
  • sudo -H gedit /etc/environment
  • Type your password
  • Edit the text file just opened:
DB_NAME=test
DB_HOST=localhost
DB_PASSWORD=password
Enter fullscreen mode Exit fullscreen mode
  • Save, then logout and log back in for the changes to take effect.

Having set the environment variables you can now change your code to use the variables instead of hard coding.

$env = getenv();

$user = $env['DB_USER'];
$password = $env['DB_PASSWORD'];
$host = $env['HOST'];

$db = new Database();
$db->connect($host, $user, $password);
Enter fullscreen mode Exit fullscreen mode

For those using a shared server with Apache. You will need to have an .htaccess file on the root folder. Normally public_html.
To set the environment variables, add the following into the file

SetEnv DB_USER your_production_db_user
SetEnv DB_PASSWORD your_production_db_password
SetEnv DB_NAME your_prodution_db_name
Enter fullscreen mode Exit fullscreen mode

This sets the variables to the server. This has one drawback since getenv() only gets system environment variables. To remedy this you can merge both getenv() and $_SERVER to one array.

$env = array_merge(getenv(), $_SERVER);
Enter fullscreen mode Exit fullscreen mode

I try as much as possible to avoid setting environment variables on my development machine, coz i just have so much going on on my machine. I What i normally do is have defaults in case the environment variable are not found on.

$user = $env['DB_USER'] ?? 'root';
$password = $env['DB_PASSWORD'] ?? 'password';
$host = $env['HOST'] ?? 'locahost';
Enter fullscreen mode Exit fullscreen mode

Now that you have done that deploying comes very easy as you don't have to change anything in your code to make connection to a database. And you are also not exposing your database credentials.

Latest comments (4)

Collapse
 
azazqadir profile image
Muhammad Azaz Qadir

This is a pretty useful guide. There are some PaaS, where github deployment is pretty easier. They have github deployment integrated in their platform. This means you only have to connect your server to github repo using ssh keys and then you can deploy php application in just few clicks.

Collapse
 
roomcays profile image
RoomCays

I dislike this approach as it is vulnerable for following situations:

  1. when your application requires CLI commands (such as some CRON-related cleanups) the .htaccess file is unavailable, so the variables will not be correct
  2. when your server hosts more than one application or hosts two instances of the same application (like "test" and "production") setting system-wide environment variables is not accurate

I'd recommend having separate PHP file such as config/environment.php:

<?php
return 'PRODUCTION';

and exclude it from VCS so it will not be distributed over instances of the application. Instead, in VCS provide an example/dummy of that file, like config/example.environment.php:

<?php
// Please copy this file to `environment.php` when you are
// setting application up for the first time.
// Possible values are: `DEVELOPMENT`, `TESTING`, `STAGING`, `PRODUCTION`
return 'DEVELOPMENT';

Then include the config/environment.php in application bootstrap, as soon as possible.

Of course the environment.php file can hold more data, like:

<?php
return [
    'mode' => 'DEVELOPMENT',
    'db_user' => 'foo',
    'db_pass' => 'bar',
    'db_host' => '123.456.789.012',
    'google_account' => 'blahblahblah',
];
Collapse
 
sadick profile image
Sadick • Edited

You are correct on

  1. When your application requires CLI commands (such as some CRON-related cleanups) the .htaccess file is unavailable, so the variables will not be correct

You can run those cli commands if your are not on a shared hosting environment. In the post i have stated that .htaccess is for those with a shared hosting plan (like the godaddy ones).

You wouldn't use .htaccess if you owned the server where the app is deployed. You would go with the second option i have provided. Set the evironnment variables on the system level. That way if your application requires CLI commands the variables would still be correct.

Collapse
 
gksander profile image
Grant Sander

Nice! This was useful for me. In the past I had always SSH'd into my server to change the DB credentials that were hard-coded into config files after each git pull origin master. Using environment variables is a much nicer way to handle this - and definitely more secure than hard-coding production DB credentials in config files and storing them in a git repo (even a private one).