Recommended way to manage global scope data and settings in PHP?
Asked Answered
H

4

6

After a few years in PHP development, I saw and heard various ways for storing "global scope data" (globals, constants, ini/XML/YML files, database, singleton properties...).

By "global scope data", I mean:

  • Global application/project settings such as
    • Database configuration
    • SMTP, FTP parameters
  • Database identifiers (e.g. primary key values for specific languages or countries defined in DB)
  • Global runtime settings such as
    • Enable logging / debug
    • Environment is dev / test / prod
  • etc.

... which are not supposed to change once retrieved, and need to be easily reachable in any part of the project code.

Some global data may need to be stored as associative array (so cannot be declared as constant).
For example: date formats per language. BTW, I saw this other SO question about array constants, but isn't there something more readable than using unserialize everywhere an array constant value is needed?

My main question is: what is the way you would recommend to store properly (I mean clean, readable, reliable) global scope data, and why (pros/cons)?

Thanks.

Horsefly answered 22/4, 2011 at 12:13 Comment(0)
C
2

You can look at Zend_Config for the most frequent implementations of config.

  • array (php only, immediate but scattered and harder to read)
  • ini (easy to read and write by hand)
  • xml (verbose and harder to handle but very flexible)
  • json (pretty easy to read, can be great if you want to access it directly via js too)
  • yaml (you write directly a serialized array basically)

Of course array may seem the most immediate and uncomplicated solution since it's pure PHP and doesn't need any special parser or writer.

On the other hand the other formats have clear advantages too. The Zend_Config documentation writes for example about ini files.

The INI format is specialized to provide both the ability to have a hierarchy of configuration data keys and inheritance between configuration data sections. Configuration data hierarchies are supported by separating the keys with the dot or period character (".").

Using constants is not a good idea because:

  1. your application doesn't need to see all your config options all of the time and
  2. more importantly you cannot nest constants and nesting is something really important for configuration.
Clerical answered 22/4, 2011 at 13:5 Comment(5)
Zend_Config_Ini seems somewhat useless. It's just a bloaty wrapper around parse_ini_file and array_merge. And if it could actually be used to update the settings file (more frequent topic on SO), it probably would kill the user comments still.Damiondamita
There is also Zend_Config_Writer, including Zend_Config_Writer_Ini! framework.zend.com/manual/en/…Clerical
And I wouldn't call that wrapper bloated. Especially because it provides section functionality too.Clerical
Hmm, as expected. It strips .ini comments. -- As for the [section] functionality, that's already supported by parse_ini_file. I'm still confused what the advantage is.Damiondamita
The advantage is, that you can exchange the adapter any time without changing anything in your code. That's what frameworks do, they wrap things in order to unify interfaces. If there was only ini and I was sure I would always use ini, I would agree with you that you could use parse_ini_file and array_merge and be done with it.Clerical
C
2

As my opinion, the best way to manage all configuration using INI files.

E.g. i am creating one configuration.ini file, that stores all my system configuration like, database information, url etc...

host_name="localhost";
database_name="my_database";
database_user="root";

On reading time, you just need to parse this ini file in php using php default function,

$configuration = parse_ini_file("path/to/configuration.ini");
Chui answered 22/4, 2011 at 12:26 Comment(9)
If you are parsing an ini file, why not just include a constants file? Surely that is faster and does exactly the same thing.Surety
Nowadays, all clients want that they can change configuration on their end. So if we using php variables as file all times, that make confusing client all times. So INI file is the only way to make simpler for people who have no sound of php.Chui
I'm sorry to say this, but it's a terrible idea. There's absolutely no reason whatsoever to use INI files and then parse them if you can construct an array or define constants and include them in your project. You're just adding an unneccessery step of parsing in the process.Expatriate
@B Tyler Using constants seems a good idea only at the first glance. If you think about what this would mean in terms of scope, you would realize that it is a very bad idea. You would make the configuration options accessible directly from everywhere in your software which is bound to create a maintenance nightmare. There is no good reasons why the whole application should know all config options, you need to hide the config and then provide access to it if needed only through a dedicated handler like for example a config class.Clerical
Why would it be a maintenance error if you are using constants? What would be different from creating a class that feeds the part of the app with values and having constants defined and accessible from anywhere? I'd say there is no good reason for the app NOT to know all of its config options. When you look at it, the app HAS to know it's config options.Expatriate
Why adding a parsing step when not really needed?Fluster
If you guys want to clutter your whole app with constants, go for it. What if you decide that you want to change to another way of storing configuration options? You have to go and change everything everywhere, I on the other hand, will just exchange my parser class to another adapter! Magic words are called encapsulation, single point of control, layering, etc.Clerical
Another reason why constants are not suitable for configuration is that they're not meant to be nested! Nesting is extremely important for configuration.Clerical
+1 There's nothing wrong with this answer. The only way you could improve is by wrapping all this in a class. One problem with using constants and in turn define() is that arrays aren't really supported. INIs on the other hand support nesting and more importantly cascading. So you can use 1 INI file for all your environments unlike with a constant based approach.Pampa
P
2

You can store the setting whichever way you prefer. I'm partial to PHP arrays or INI files.

Once you have that, code an accessor class that is globally available. You can make it singleton if you want, but not really required.

This class will parse your settings store and create an internal data structure. Just make sure that you don't have any setters in there so that the data cannot be overridden. Have a look at how Zend implements its Zend_Config class. This is what I'm talking about : http://framework.zend.com/manual/en/zend.config.html

Make sure your accessor class is available globally so you can get at the settings any time you want.

Pampa answered 22/4, 2011 at 12:31 Comment(0)
C
2

You can look at Zend_Config for the most frequent implementations of config.

  • array (php only, immediate but scattered and harder to read)
  • ini (easy to read and write by hand)
  • xml (verbose and harder to handle but very flexible)
  • json (pretty easy to read, can be great if you want to access it directly via js too)
  • yaml (you write directly a serialized array basically)

Of course array may seem the most immediate and uncomplicated solution since it's pure PHP and doesn't need any special parser or writer.

On the other hand the other formats have clear advantages too. The Zend_Config documentation writes for example about ini files.

The INI format is specialized to provide both the ability to have a hierarchy of configuration data keys and inheritance between configuration data sections. Configuration data hierarchies are supported by separating the keys with the dot or period character (".").

Using constants is not a good idea because:

  1. your application doesn't need to see all your config options all of the time and
  2. more importantly you cannot nest constants and nesting is something really important for configuration.
Clerical answered 22/4, 2011 at 13:5 Comment(5)
Zend_Config_Ini seems somewhat useless. It's just a bloaty wrapper around parse_ini_file and array_merge. And if it could actually be used to update the settings file (more frequent topic on SO), it probably would kill the user comments still.Damiondamita
There is also Zend_Config_Writer, including Zend_Config_Writer_Ini! framework.zend.com/manual/en/…Clerical
And I wouldn't call that wrapper bloated. Especially because it provides section functionality too.Clerical
Hmm, as expected. It strips .ini comments. -- As for the [section] functionality, that's already supported by parse_ini_file. I'm still confused what the advantage is.Damiondamita
The advantage is, that you can exchange the adapter any time without changing anything in your code. That's what frameworks do, they wrap things in order to unify interfaces. If there was only ini and I was sure I would always use ini, I would agree with you that you could use parse_ini_file and array_merge and be done with it.Clerical
N
1

parse_ini_file

; This is a sample configuration file
; Comments start with ';', as in php.ini

[first_section]
one = 1
five = 5
animal = BIRD

[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"

; This is an array
[third_section]
phpversion[] = "5.0"
phpversion[] = "5.1"
phpversion[] = "5.2"
phpversion[] = "5.3"

Also adding this to the INI file (first lines in the file) helps keep it secure:

;<?php die("<br /><br /><br /><br /><br /><h3>404 Not Found</h3><br /><br />The requested resource could not be found."); ?>
;Secure INI file
Nephrectomy answered 22/4, 2011 at 12:33 Comment(8)
Why adding a parse step when not needed?Fluster
@Charliepiga why do you think parsing an ini is an unwanted step?Pampa
@JohnP, because it's useless. You parse a file to get an array of values instead of defining it already as an array...Fluster
@Charliepiga you realize you can't actually define() arrays right? define() only supports scalar. Also, unlike a multidimensional array INI files are much easier to read and they cascade wellPampa
@JohnP, I've never mentioned the define() function. I was thinking more about a singleton instead associated to a config file that defines configurations as $c = array().Fluster
@Charliepiga my mistake, when you said 'defining' I assumed the worst :) However, the point still stands regarding sections and cascades. You'd need to have multiple arrays or some kind of transform for you to have 1 file and multiple configurations for your different environmentsPampa
@JohnP, I don't get what's so cool about [first_section] \n one = 1 instead of $c['first_section']['one'] = 1. With arrays you can easily set booleans too. You should hack it with the php.ini file and convert 1 to true and 0 to false.Fluster
@Charliepiga That's the good thing! Any settings not defined in second_section are taken from the settings in first_section. You can't do that with the array unless you code it. If you do, you might as well use INIsPampa

© 2022 - 2024 — McMap. All rights reserved.