-2
\$\begingroup\$

I am creating config file for every other project and try to set all necessary things at once but sometimes miss the things.I have used many framework but most of time I need core and minimal config file

Can you please highlight what things must be included in config file.

right now what I do in config

  • namespace
  • add constant for project title and meta ( we can use contact file)
  • database table name files
  • includecommon function file
  • define constant for relative and absolute path and URI
  • include debugging class
  • include autoload function
  • include DB connection.
  • ini_set()
  • session_start()
  • ob_start()

Here is my basic config file.

namespace GetReady;

/**
 * A simple, clean and secure PHP Config class
 *
 *
 * A simple PHP  Config file embedded into a small framework.
 *
 * @access private
 * @internal  use Kint class for debugging
 * @author X <nomail@boun.cr>
 * @example  this file is Config File
 * @date( Jan 2015)
 * @see Kint class required to check the outout
 * @todo  change `d()`into `var_dump()` if you do not have Kint class.
 * @license http://opensource.org/licenses/MIT MIT License
 * **/

use PDO;

ini_set('session.bug_compat_warn', 0);
ini_set('session.bug_compat_42', 0);

error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set('xdebug.collect_params', '4');
ini_set('xdebug.collect_vars', 'on');
ini_set('xdebug.collect_return', '1');
// var_dump(__DIR__);
// checking for minimum PHP version
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
    exit("Sorry, Simple PHP Login does not run on a PHP version smaller than 5.3.7 !");
}

spl_autoload_extensions(".php");
spl_autoload_register('loadclass');

session_start();
// d($_SERVER);
$scheme = $_SERVER['REQUEST_SCHEME'];
//debugging purpose class
define('DS', DIRECTORY_SEPARATOR);
define('PROTOCOL', $_SERVER['REQUEST_SCHEME'].':'.DS.DS); // http://
define('PROJECT_FOLDER', basename(dirname(__DIR__))); // ==> 'folder'
define('HOST', $_SERVER['HTTP_HOST']); // ==> '192.168.0.228|localhost|server host'
define('URL', PROTOCOL.HOST.DS.PROJECT_FOLDER);  //'http://192.168.0.228/folder'
define('PATH', $_SERVER['DOCUMENT_ROOT'].PROJECT_FOLDER);  // ==> '/opt/lampp/htdocs/spl'
// +d(array_slice(get_defined_constants(), -7, 10, true) );

$sitename = 'Site Title';
$general_email = 'info@domain.com';    

include_once($base_path.DS.'vendor/autoload.php'); 

include_once(__DIR__.'functions.php');    

$dsn = 'mysql:dbname=db_name;host=localhost';
$user = 'root';
$password = '****';

//A PDO connection
try {
    $pdo = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
    // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    exit();
}

Will you please suggest anything more relevant which must be on config files.

\$\endgroup\$
  • \$\begingroup\$ why downvoted? Did i ask something irrelevant? \$\endgroup\$ – diEcho Feb 4 '15 at 6:36
3
\$\begingroup\$

Before reading on please keep in mind that this might seem harsh, but I have no other intention than to help you write better code. I know from myself it takes some time to ask for help/review, so keep going! I think the reason you have gotten downvotes is because this is a very broad question when you look at the code provided. But I will try to mention the things I see as an issue.

This has too many responsibilities to fit the definition of a config file. First of I would name this file bootstrap. This is because several things required for the application to work is initialized here.So where should I store my configurations then? What I would do is create a file named config.php and declare an associative array inside it and return it at the end.

// config.php

$config = [
    'general' => [
        'sitename' => 'awesomeness',
        'email'    => 'email@email.email'
    ]
    'database' => [
        'dsn'      => 'mysql:host=localhost;dbname=db_name',
        'username' => 'username',
        'password' => 'pass'
    ]
];

return $config; // Important!

This has 2 main benefits. First off you save resources/increase speed as PHP doesn't have to interpret a new file format like JSON, ini or XML. Second you can have nested configurations. This means you can easily create groups of configurations.

To use the configurations you would do the following:

$config = require 'path/to/config.php';

Because the config file returns the array the require will assign that value to the $config variable. You can now access your configurations like a normal array.

$dsn = $config['database']['dsn'];

Then to declare constants and start sessions, database and output buffering is all something you would do inside your bootstrap.php file. I have taken the code you provided and refactored it some. I have added comments here and there to address issues that didn't require its own section. I have also assumed this is the first file included as autoloading, functions and such is included here.

// bootstrap.php

session_start();

$scheme = $_SERVER['REQUEST_SCHEME'];

/*
 * This is counter intuitive as it obscures what DS really is and add
 * a new constant with the same value. This doesn't really serve any purpose 
 * other than you saving some keystrokes at the cost of readability.
 * I would not use it.
 */
define('DS', DIRECTORY_SEPARATOR);

/*
 * You should not use DS here as they can change from different OS to OS.
 * The HTTP protocol will only accept double forward-slashes.
 *
 * You can also reuse your $scheme variable here.
 */
define('PROTOCOL',       $scheme . '://');
define('PROJECT_FOLDER', basename(dirname(__DIR__)));
define('HOST', $_SERVER['HTTP_HOST']);

/*
 * The DS here will add a third slash making the URL look like:
 * 
 * http:///project_folder - This is an invalid URL.
 */
define('URL',  PROTOCOL . HOST . PROJECT_FOLDER);
define('PATH', $_SERVER['DOCUMENT_ROOT'] . PROJECT_FOLDER);

/*
 * Where does $base_path come from? Remember this should be the first
 * file that is loaded since it instantiates so many things.
 *
 * I have also change include_once to include as these files should never even
 * have the possibility to be included more than once. It also saves resources.
 */
include $base_path . DS . 'vendor/autoload.php'; 
include __DIR__ . 'functions.php';    

$config = require 'path/to/config.php';

$dsn      = $config['database']['dsn'];
$username = $config['database']['username'];
$password = $config['database']['password'];

try {

    /*
     * Declare the error mode as exception from the start
     * instead of altering it right after instantiation of the PDO object.
     *
     * I also added ATTR_EMULATE_PREPARES to force PDO to use prepared statements.
     */
    $options = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES => false
    );

    $pdo = new PDO($dsn, $user, $password, $options);

} catch(PDOException $e) {

    /*
     * This can be dangerous. Often when PDO fails the connection details such as
     * the DSN, username and password are leaked in the error message. By displaying
     * the error to the screen a malicious user could attack your website!
     *
     * Just provide a generic error message like: 'Application error' and log the
     * actual message (should be logged by PHP automatically if the INI 
     * configuration 'log_errors' is enabled).
     */
    exit('Connection failed: ' . $e->getMessage()); // Can echo from the exit() function.

}

Notes on the code you provided.

You should consider declaring the error reporting level at the very top to ensure you don't miss any potential bugs/errors. Use the following:

/*
 * The -1 equals every single error, warning, notice and
 * strict standards warning.
 */
error_reporting(-1);

This isn't strictly an error, but having too many constants can be confusing. Remember the following:

Always try to keep the code as simple as possible and only add functionality when needed. If code doesn't serve a purpose remove it.

If you are familiar with classes you could try to encapsulate your constants regarding PROTOCOL, HOST, URL and PATH inside a class named request? This would allow you to keep your code clean and more readable. While at the same time group related functionality, so when things so south you know where to start looking :D

Are you sure each and every page load requires a database connection? A database connection is expensive to make and maintain. It is recommended only to create the connection when you are certain it will be used.

You mentioned output buffering. It might course you trouble down the road. If you want to echo a variable for testing it wont display as the buffering has stored it. Also maybe not every request requires output buffering. If you some time in the future use this at the top of a script which called with AJAX and the script inserts into the database. No output is generated, but PHP engine has to use resources to maintain it. That doesn't seem right :D

More advanced stuff and not required is the sessions. Are you sure each request requires the session initialized? If so nothing is wrong, but maybe the session is irrelevant for your landing/homepage? You could again make some functionality which detects this or a class that keeps track of this. This is a said quite advanced to do properly. If you feel up for it search a little around the web to get some ideas.

Happy coding out there!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.