Setting Up A Simple Configuration

The idea behind setting up a configuration file is that the configuration file lives in a particular mode and doesn't change when pushing code from dev to staging to production. It would be one of the very few files that would not change.

A config file can be set up in any format with any type of configuration options. For our purposes, we just need to set up a way to specify what mode the software should run in, and the database options such as username, password, and host. We can expand this in the future, but for now, let's keep it simple.

Let's define a simple configuration file.

This code should be put into config.php in your webroot directory.

<?php
namespace config;

class config {
	static public $host = "localhost";
	static public $username = "[username]";
	static public $password = "[password]";
	static public $dbName = "employees";
	
	// this can be "dev", "staging", or "prod"
	static public $mode = "dev";
}

What we have here is a simple class that defines the database configuration and mode of the software.

In our index.php file we'll do a simple include to add the config.php file to index.php.

This code should be put into index.php in your webroot directory.

<?php

// include the config
include "config.php";

// use \config\config to make it easier to type in our code
use \config\config;

$db = null;

try {
	
	// make a connection to the MySQL server using db configuration
	$db = new PDO("mysql:host=".config::$host.";dbname=".config::$dbName.";", config::$username, config::$password);

	// turn on PDO options
	$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

} catch(PDOException $e) {
	
	// check to see if mode is "dev" or "staging"/"prod"
	if (config::$mode == "dev") {
		// if dev, then we want to show errors in our browser
		echo "Couldn't connect to MySQL server:<br>";
		echo $e->getMessage() . "<br>";
		exit;
	} else {
		// if staging or prod, we only want errors to show up in our system log
		syslog(LOG_ERR, "Couldn't connect to MySQL server: " . $e->getMessage());
		exit;
	}
}

$results = [];

try {

	// prepare a query
	$prep = $db->prepare("select lastName, firstName, state from names n left join addresses a on n.id=a.nameId order by state");
	
	// execute the query
	$prep->execute();
	
	// fetch the results and put them into a variable
	$results = $prep->fetchAll();

} catch(PDOException $e) {
	
	if (config::$mode == "dev") {
		// if dev, then we want to show errors in our browser
		echo "There was a database error:<br>";
		echo $e->getMessage() . "<br>";
		exit;
	} else {
		// if staging or prod, we only want errors to show up in our system log
		syslog(LOG_ERR, "There was a database error: " . $e->getMessage());
		exit;
	}
	
}

// echo the results to the browser
foreach ($results as $res) {
	echo "<div>{$res["lastName"]}, {$res["firstName"]} in {$res["state"]}</div>";
}


------

In this code we've made a few changes. Let's look at a few of them in more detail.

// include the config
include "config.php";

This block of code makes PHP load config.php into index.php, so you can use the code. Basically, it's like typing all the code in config.php into index.php at the top of the file. You can also include code where ever you want, although it's not exactly good practice in most instances.

------

// use \config\config to make it easier to type in our code
use \config\config;

We want to get into the habit of using our code in our files for the future. In the future, we'll be autoloading (auto-including) our code without using includes. One of the ways we do that is by using use. use also allows us to cut down on typing. If we didn't use a class, we would have to type more. For example, we can get our host from the config like this: \config\config::$host. But, for every time we need to get something from the config class, we must type \config\ beforehand. If we use it, then we don't have to do that and we can shorten the amount of typing we must do.

------

// make a connection to the MySQL server using db configuration
$db = new PDO("mysql:host=".config::$host.";dbname=".config::$dbName.";", config::$username, config::$password);

In this code, we have our PHP PDO connection updated to use the options that are specified in config.php. Because we included use \config\config; previously, we can use config::$variable to access the needed configuration option.

You'll see that to access our database host, we specify config::$host. The same goes for config::$username and config::$password.

------

if (config::$mode == "dev") {
	// if dev, then we want to show errors in our browser
	echo "There was a database error:
"; echo $e->getMessage() . "
"; exit; } else { // if staging or prod, we only want errors to show up in our system log syslog(LOG_ERR, "There was a database error: " . $e->getMessage()); exit; }

In this block of code, we're using an if statement to decide whether or not we want to show errors on the screen.

When configuring your config.php file, we want to specify what mode we're in, depending on what server config.php resides on.

For example, if you're working on the code on your dev machine, your config.php would specify dev in the string.

If config.php resides on any other server, we would specify either staging or prod and our code would then send all errors to our syslog.

Earlier we talked about config.php being one of a very few files that would not change. The reason for that is, if we push our config.php file from our dev machine, we would then change the mode on staging and possibly prod. That might be bad for security because you're exposing details about your applications that make it easier for attackers to glean information about your database layout. Thus, it would make it easier to do SQL inject attacks.