CodeIgniter 3 - Tips to setup your project

CodeIgniter (CI) is a fantastic MVC (Model-View-Controller) framework for PHP web app development. Many people use it for personal or professional projects. In this blog, I will discuss few tips to setup the configuration for your project.

1.) Setting up environment:

 It is very important to set the ENVIRONMENT variable in index.php file. You first develop, test and then move your application to Production. Depending on these phases, your project needs different configurations like API key, payment gateway key etc. For example, when you develop or test your app, you need to connect to the payment gateway's sandbox instance with the sandbox's credentials and when you are ready for prod, you connect to the payment gateway's production instance with real credentials.

How to setup the environment properly? Open the index.php and search for the text:

define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development');

This will set the environment depending on the environment variable CI_ENV set in the .htaccess file. Open the .htaccess file and put the below line of code for Apache:

SetEnv CI_ENV production

This will automatically set the $_SERVER['CI_ENV'] variable and depending on the value in .htaccess file the ENVIRONMENT constant will be defined.

To test it has setup properly, just create a function in Welcome controller:

public function env_test()
{
   echo ENVIRONMENT;
}

 2.) Setting up custom configuration file:

You can setup custom configuration in CodeIgniter apart from the CI's standard config.php file. To setup your own project specific custom configurations, first open the application/config/autoload.php file and search for the section where configurations are auto loaded.

$autoload['config'] = array();

change it to:

$autoload['config'] = array('custom_config');

And create new file name custom_config.php under directory application/config/ . Here you can define your application specific configuration setup. For example:

//Password Salt
$config['password_salt'] = 'MYAPP_Passwrod_Salt_01234';

//Set maximum SMS verification allowed per user
$config['max_sms_verify_allowed'] = 5;

To test your custom configurations are working, write a test controller function under Welcome controller.

public function test_config()
{
   echo $this->config->item('max_sms_verify_allowed');
   echo '<br>';
   echo $this->config->item('password_salt');
}

Call the controller and method using your browser and you see new you can access your custom config.

3.) Setting Up custom configuration based on environment:

Now you can setup custom configuration based on your application ENVIRONMENT. This is very helpful when you deal with external application like Facebook SDK or payment gateway like Paypal. You need to have different keys based on either sandbox instance or production instance. Consider a scenario when you connect to Paypal's sandbox instance when test your application you will have different keys compared to when you connect to Paypal's production instance when you set your environment to production.

Considering you will have three different ENVIRONMENT values development, testing, production for ENVIRONMENT constant as shown in step 1 of this tutorial, create three files named

  • custom_config_development.php
  • custom_config_testing.php
  • custom_config_production.php

under directory application/config/ and write the below code with different values in these three files accordingly.

//Configuration for PayPal gateway
$config['paypal_server'] = 'www.sandbox.paypal.com';
$config['paypal_gateway_url'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
$config['paypal_merchant_id'] = 'MYPAYPAL_SANDBOX_ID';
$config['paypal_business_email'] = 'MYBUSINESSEMAIL';
$config['paypal_secret_key'] = 'PAYPAL_SANDBOX_SECRET_KEY';

Change this values accordingly in the respective testing and production config files. For example the production configuration could be:

//Configuration for PayPal gateway
$config['paypal_server'] = 'www.paypal.com';
$config['paypal_gateway_url'] = 'https://www.paypal.com/cgi-bin/webscr';
$config['paypal_merchant_id'] = 'MYPAYPAL_PROD_ID';
$config['paypal_business_email'] = 'MYBUSINESSEMAIL';
$config['paypal_secret_key'] = 'PAYPAL_PROD_SECRET_KEY';

Now you have to include these files in the custom_config.php file. Depending on the ENVIRONMENT constant, it will include the respective custom environment specific variable automatically.

// Include the custom environment or instance specific config file
$custon_env_config_file_name = 'custom_config_' . ENVIRONMENT . '.php';
if(file_exists(APPPATH.'config/'.$custon_env_config_file_name))
   include_once $custon_env_config_file_name;

 

To test it is working create a controller method like below:

public function test_config()
{
   echo ENVIRONMENT;
   echo '<br>';
   echo $this->config->item('paypal_server');
   echo '<br>';
   echo $this->config->item('paypal_gateway_url');
}

 4.) Setup base URL:

Change the config.php under directory application/config and include the below code instead of the standard base URL set. This will automatically take your base URL when you move your code to web hosting server with actual URL.

Note: Here for development on local host, I have setup a virtual host "moedemoci3.dev" in my WAMP server. You may read this blog article on How to setup virtual host.

if(ENVIRONMENT === 'development')
	$config['base_url'] = 'http://moedemoci3.dev';
else 
	$config['base_url'] = 'https://www.myprodurl.com';

$config['index_page'] = '';

 5.) Setup Error reporting and logging:

By default CodeIgniter (CI) enables error reporting On for development environment and turns it off for testing and production. You should not change this for security reason. But you can change the log message behavior in config.php file. By default CodeIgniter turns off logging by setting in the below code:

$config['log_threshold'] = 0;

But we want a little dynamic approach for it. For development and testing environment, we want to enable 'error' and 'debug' messages but only 'error' messages for production environment. Change the code as below:

if(ENVIRONMENT === 'development' || ENVIRONMENT === 'testing')
{
	$config['log_threshold'] = array(1, 2);
}
else 
{
	$config['log_threshold'] = 1;
}

6.) XSS and CSRF security in CodeIgniter:

By default CI turns off global XSS filtering by the below configuration in config.php file.

$config['global_xss_filtering'] = FALSE;

I will prefer to keep it turned off and we will handle the HTML escaping in all our code. But you need to turn on the CSRF protection which is off by default. Modify the CSRF code as below and regenerate the token. Many developers face problems with AJAX call when CSRF is turned On and thus keep it off. But one should turn it on.

$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
$config['csrf_exclude_uris'] = array();

You may exclude the URIs to ignore CSRF validation but setting the $config['csrf_exclude_uris'] settings. for example:

$config['csrf_exclude_uris'] = array('webpayment/paypal-return', 'webpayment/paypal-ipn');

7.) Database Configuration:

The database configuration in CodeIgniter resides in application/config/database.php file. You can tweak the code inside to make your code working for different database for different environment. This will be very useful as you will develop your website in local machine but the testing and production environment will be on your web hosting server. You have to change the database settings like database username, password every time you change your environment.

The below code in database.php file will help you to write the code once and will change according to your environment.

//$active_group = 'default';
$active_group = ENVIRONMENT;
$query_builder = TRUE;

//Database configuration for development on local machine
$db['development'] = array(
	'dsn'	=> '',
	'hostname' => 'localhost',
	'username' => 'localhost_user',
	'password' => 'localhost_password',
	'database' => 'localhost_db_name',
	'dbdriver' => 'mysqli',
	'dbprefix' => '',
	'pconnect' => FALSE,
	'db_debug' => TRUE,
	'cache_on' => FALSE,
	'cachedir' => '',
	'char_set' => 'utf8',
	'dbcollat' => 'utf8_general_ci',
	'swap_pre' => '',
	'encrypt' => FALSE,
	'compress' => FALSE,
	'stricton' => FALSE,
	'failover' => array(),
	'save_queries' => TRUE
);

//Database configuration for testing on production server
$db['testing'] = array(
	'dsn'	=> '',
	'hostname' => 'localhost',
	'username' => 'test_username',
	'password' => 'test_password',
	'database' => 'test_database',
	'dbdriver' => 'mysqli',
	'dbprefix' => '',
	'pconnect' => FALSE,
	'db_debug' => FALSE,
	'cache_on' => FALSE,
	'cachedir' => '',
	'char_set' => 'utf8',
	'dbcollat' => 'utf8_general_ci',
	'swap_pre' => '',
	'encrypt' => FALSE,
	'compress' => FALSE,
	'stricton' => FALSE,
	'failover' => array(),
	'save_queries' => TRUE
);

//Database configuration for production when the website is live
$db['production'] = array(
	'dsn'	=> '',
	'hostname' => 'localhost',
	'username' => 'prod_username',
	'password' => 'prod_password',
	'database' => 'prod_database_name',
	'dbdriver' => 'mysqli',
	'dbprefix' => '',
	'pconnect' => FALSE,
	'db_debug' => FALSE,
	'cache_on' => FALSE,
	'cachedir' => '',
	'char_set' => 'utf8',
	'dbcollat' => 'utf8_general_ci',
	'swap_pre' => '',
	'encrypt' => FALSE,
	'compress' => FALSE,
	'stricton' => FALSE,
	'failover' => array(),
	'save_queries' => TRUE
);

Remember to change the username, password and the database values according to your application setup. Also this setup gives you flexibility to setup different configuration differently as the 'db_debug' would be TRUE in development instance but should be FALSE in test or production instance.

That's it for time being! Happy coding with CodeIgniter. Please feel free to write a comment if you have better suggestions and include some point which I have missed.

Comments