Is it recommended to use constants for configuring a PHP project?

Asked

Viewed 1,094 times

15

It is very common to see constants in a configuration file in a PHP project, but I would like to know if this is really the best practice, because I think if I store the password of a database in a file config.php it can be used anywhere, IE, accessible throughout my project, I do not know if it would fit the standard (or anti-standard) "God Object", but constant would be the best solution for this type of problem?

8 answers

13


Of all the PHP frameworks I’ve worked with to date, none of them used constants to store database connection data (and other things, for example).

I often see this use of constants in older libraries.

In the CakePHP 2, was used constants for database configuration, but it was within a class.

Example:

class DB_CONFIG
{
    const HOST = 'nome_do_host';
    ...
}

In the Laravel 4 e 5, use a configuration file that returns a array with the connection data, being read only by the location where it is included.

The Symfony 2 uses yaml by default, other options may also be used.

I would not recommend the use of constants, unless it was a specific namespace or a class, as in Cakephp 2.

It is also worth remembering that, regardless of the ways I highlighted and idependente to use constant or not, all of the above were unanimous in one thing: The configuration location is separate and easy to find. This improves the life of the programmer, when it has to configure the application. Because it is common for people to mix script for configuration and script output data, which generates a lot of confusion.

In the end, what can matter is more the organization than the medium itself where the data is stored.

It is worth remembering that in the versions of PHP 5.6 >=, we can use array constants. This makes it easier to use than to use prefixes for constants.

PHP Example Currently:

define('DB_HOST', 'localhost');
define('DB_USER', 'username');
define('DB_PASSWORD', 'SENHA'); 

Exmeplo PHP 5.6 >:

define('DB', [
    'HOST' => 'localhost',
    'USER' => 'username',
    'PASSWORD' => 'SENHA'
]);

OR

const DB = [ 'HOST' => 'localhost', ...];

Other forms

In PHP it is also possible to use files ini and json.

In the case of json:

config.json

   {
     "DB": {
         "HOST" : 'localhost'
     }
   }

Loading the JSON:

json_decode(file_get_contents('config.json'));

Example ini:

config.ini

[DB]
HOST=localhost
PASSWORD=senha

In PHP:

parse_ini_file('config.ini', true);

Note: These last two cases should be separated into directories not accessible to the client, since the browser can read its content as text, if it is listed

  • Very interesting this solution, but in case I use an INI for example, it would be good to have a class (model) just to read and bring this information when necessary, correct?

  • 1

    Also possible! It would be more interesting if this model detected on index [DB] and [DB_LOCAL], for you already configure once only the connection data in production (as in Laravel). Hence you only need to inform your application whether it is in production or local for it to perform connection data exchange automatically

  • 1

    I will give a study in Laravel, although I want to avoid the use of frameworks because I am learning and developing a CMS from scratch (just for study), I think learning from them will help a lot.

6

I don’t think this can be considered God Object, doesn’t seem to me even an object, maybe I wanted to talk about something else.

This is not the best practice but it is much practiced without causing major problems in practice. That depends on how secure you need access to the data. Obviously with the password exposed, other people who have access to the server will have access to the bank, but probably the bank will also not be encrypted, so it makes little difference.

If you really need security, authentication cannot be done in this way, you would need access to the bank only with a password passed by the user in a secure way. Which is unviable in case the user is anonymous. So you could use a password stored somewhere but encrypted. This does not mean that safety is absolute.

It makes no difference whether it’s constant or stored otherwise. It will not change anything put in another way, constants must be avoided, but some that clearly has global function, has no problems.

6

To constant is not a recommendation to use in settings, is a way to maintain a constant datum throughout your project, which will be used repeatedly in various places.

In various situations, we may have constants with data that will be maintained throughout your project, such as the two examples below:

//resumo da constante do php de diretório    
define('DS', DIRECTORY_SEPARATOR); 
//caminho físico da aplicação
define('APPLICATION_PATH', '..' . DS . dirname(__DIR__) . DS);  

What makes it different is the ease of maintenance "manual" (if necessary, which should hardly be).

One of the recommendations for use is in your aggregation of events defined with setenv, which may be setting parameters for the development environment. How Zend Framework already uses host virtualization:

yourproject.conf

<VirtualHost *:80>
     ServerName yourproject.local
     DocumentRoot /var/www/YourProject/public
     SetEnv APPLICATION_ENV "development"
     <Directory /var/www/YourProject/publicc>
          DirectoryIndex index.php
          AllowOverride All
          Order allow,deny
          Allow from all
     </Directory>
</VirtualHost>

PHP

// Define application environment
defined('APPLICATION_ENV') ||
define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ?
getenv('APPLICATION_ENV') : 'production'));

That is, when using constant, assume that it will be something that will not change (never? Who knows...).

In short: constant is what the name itself and its behavior says, something constant, that doesn’t change. If in your application you have something like this, use, to not have to smash lumps later of things that never need to change.

Example of use of constant with class:

class AppPath
{
   const APPLICATION_PATH = "/path/app/";

   public function __construct()
   {
       echo self::APPLICATION_PATH;
   }
}

//instanciando a classe, o construtor retornará a constante
return new AppPath(); 
  • I liked your solution, and for example, if I need to use a constant like APPLICATION_PATH, can I use it directly in a class or should I inject it through parameters? Thank you.

  • The use of a global constant can be done in an abstract class (not instance), or in a bootstrap or autoload file of a mvc application outside the class, since it will be in the whole project. You can also use it within control or entity classes, but it will only have use within the same, unless you have an inheritance assigned to the other classes.

  • Just one touch: The last example does not work, because the __construct does not return values in PHP

  • 1

    True, I forgot this detail, thank you @Wallacemaxters

5

It depends a lot on the type of configuration you want to store and the architecture of your system. For example, settings that are managed per user, for example: color, size, style, layout and etc would be preferable if it did not store in constants, because as the name itself says, are constant and therefore should remain with a single value from the moment they are set.

However, if your system has a unique login and you need to make use of the customer password, I see no problem in creating a constant with the password. Provided that its value does not change during the execution of the programme.

5

Passwords and access data I already prefer encapsulate and only my connection class/or similar have access to this data. I think any form of variable too accessible somehow compromises the security of your application.

  • 1

    That’s what I thought when I saw the Wordpress source code, right at the beginning to facilitate user configuration you type the database password into a constant (define('DB_PASWORD', 'password_here'); but these days playing with some functions in a plugin I saw that simply anyone can get access to constant with the password, which would be very insecure, seeing the wide range of plugins that Wordpress offers and the ease that is to publish one. Of course this is a very specific case, but it is a doubt that I have always had in my projects.

4

Better centralize your data in a configuration file.

If you will use with define, or if you will use a . env (dotEnv), it doesn’t make much difference.

Just don’t leave it fixed in the code because it makes maintenance difficult.

4

Constants are used as pieces of information reusable from formal (usually) global and immutable, that is, it does not change.

In case you create a password constant for your database it is highly recommended that it be encrypted before setting.

When God Object is basically a class or object that functions as a function repository, class/object has more than one responsibility.

  • Particularly, @rray, I hate told! Remembering prefixes and names is boring! For example, the constants that are flag of the filter_var. For me, this makes the situation difficult! But there are cases where its use is very applicable.

  • @Wallacemaxters, constants don’t need prefixes :P, nobody complains about TB_(I’m not a fan of prefixes). They are also a way to make information accessible in a unique way as for example create a constant to burst the value in seconds of an hour or day, is much that of playing on local variables loose. Just so I don’t miss the fun, define('MUDANÇA', true); :D

  • If you do not use prefix, it is even worse. Then you will mess up all the bagaça. I would prefer to use a namespace, or even an array in a configuration file with the famous return array(...);

  • @Wallacemaxters you will not need so many constants so :P. I agree that it is better to play this information in file apart, sometimes the php application has the code obfuscated or 'closed', ai vai alterar a linha de configuração do banco como sem gerar um novo build?

  • I liked the definition you gave for your answer, just meddling in the conversation, how would I use an encrypted password when it would have to be read by some class? And another question in particular, would you have any good articles to tell me about namespaces in PHP? I tried to use it but I got very confused.

  • Do you have any incorrect information in the reply? can I correct.

Show 1 more comment

3

You must use constants only to store information that do not change and shall be accessible anywhere in the project.

In all other cases, I recommend using a configuration file accessible through a configuration class

Example: Config::get( 'databases.main' ).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.