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.

Community
  • 1
  • 1
Maxime Pacary
  • 22,336
  • 11
  • 85
  • 113

4 Answers4

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");
Sanjay Mohnani
  • 990
  • 7
  • 18
  • 1
    If you are parsing an `ini` file, why not just include a constants file? Surely that is faster and does exactly the same thing. – satnhak Apr 22 '11 at 12:32
  • 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. – Sanjay Mohnani Apr 22 '11 at 12:36
  • 1
    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. – Michael J.V. Apr 22 '11 at 12:37
  • @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. – markus Apr 22 '11 at 12:57
  • 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. – Michael J.V. Apr 22 '11 at 13:01
  • Why adding a parsing step when not really needed? – Shoe Apr 22 '11 at 13:12
  • 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. – markus Apr 22 '11 at 13:16
  • 1
    Another reason why constants are not suitable for configuration is that they're not meant to be nested! Nesting is extremely important for configuration. – markus Apr 22 '11 at 13:23
  • +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. – JohnP Apr 22 '11 at 13:58
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.

JohnP
  • 49,507
  • 13
  • 108
  • 140
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.
Maxime Pacary
  • 22,336
  • 11
  • 85
  • 113
markus
  • 40,136
  • 23
  • 97
  • 142
  • 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. – mario Apr 22 '11 at 13:23
  • There is also Zend_Config_Writer, including Zend_Config_Writer_Ini! http://framework.zend.com/manual/en/zend.config.writer.introduction.html – markus Apr 22 '11 at 13:25
  • And I wouldn't call that wrapper bloated. Especially because it provides section functionality too. – markus Apr 22 '11 at 13:27
  • 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. – mario Apr 22 '11 at 13:35
  • 1
    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. – markus Apr 22 '11 at 13:42
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
Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
  • Why adding a parse step when not needed? – Shoe Apr 22 '11 at 13:12
  • @Charliepiga why do you think parsing an ini is an unwanted step? – JohnP Apr 22 '11 at 13:58
  • @JohnP, because it's useless. You parse a file to get an array of values instead of defining it already as an array... – Shoe Apr 22 '11 at 13:59
  • @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 well – JohnP Apr 22 '11 at 14:03
  • @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()`. – Shoe Apr 22 '11 at 14:14
  • @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 environments – JohnP Apr 22 '11 at 14:16
  • @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. – Shoe Apr 22 '11 at 14:20
  • @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 INIs – JohnP Apr 22 '11 at 14:42