views:

462

answers:

4

I need to be able to store data for a php application in a file. I need to be able to do this without any sort of external dependencies other than PHP itself.

Here are the requirements I have:

  • Settings will not be updated/added/removed very often. So updating of settings does not have to be very efficient. However, I do want to be able to do this all through a PHP script, not through editing of files.
  • Settings will be read constantly, so reading of settings must be very efficient.
  • Settings are in a unique format, if I had them in an array it might be something like $Settings["Database"]["AccessSettings"]["Username"]["myDBUsername"];
    $Settings["Database"]["AccessSettings"]["Password"]["myDBPassword"];

I would prefer to not have settings stored in arrays like I mentioned above. Instead I would prefer some access methods: getConfig("Database","Accesssettings","Username") would return 'myDBUsername'. The reason for this is I want to limit the variables I am storing in the global scope.

What would the best way of getting/retrieving these be?

Do the the hierarchy I was thinking possibly an xml file, but I wasn't sure what PHP was like for accessing xml files (particularly the fact that I need to be able to add, edit, and remove). If it should be XML what sort of xml access should I look into.

If it is another format, I would like some pointers to the right direction for what to look into for how to use that format.

A: 

If you're not hand editing, use serialized data.

Writing config using serialize:

file_put_contents('myConfig.txt', serialize($Settings));

Reading config using unserialize:

$Settings = unserialize(file_get_contents('myConfig.txt'));

You could write a class for modifying and getting values for this data using PHP magic functions __get() and __set().

Crad
This will horribly fail on parallel access by multiple clients.
vog
Please clarify, of course you'd have collisions with multiple setters, but there would be no problem with multiple readers. Author of the question says "Settings will not be updated/added/removed very often. So updating of settings does not have to be very efficient. However, I do want to be able to do this all through a PHP script, not through editing of files."
Crad
@Crad: Wish we could vote down comments.
hobodave
Of course I meant parallel write access. There's a difference between "parallel writes cleanly overwrite each other" and "parallel writes leave a mess which can't be read in anymore". Although the first variant might be acceptable, the second one definitely isn't. However, the second scenario is possible since file_put_contents() is not atomic.
vog
@hobodave: Please don't take the votes personally. I don't know whether you noticed, but _I_ removed my answer after you explained to me why it was misguided.
vog
+2  A: 

Brian, parse_ini_file is what you need.

Ah, I missed the requirement that you'd be editing this via PHP.

In that case there is nothing native to PHP that you can use for this purpose. You'd have to roll your own.

You could save yourself a ton of time by simply using Zend_Config_Ini though. I know you state that you don't want to use anything else, but Zend Framework is structured to allow you to use whatever pieces of it you need. Zend_Config can be used on it's own. You can certainly just add these few classes to your project and let them handle your INI file parsing.

Here is an example using your samples above:

[config]
Database.AccessSettings.Username = myDBUsername
Database.AccessSettings.Password = myDBPassword

You would load and access this as simply as:

$config = new Zend_Config_Ini('/path/to/ini', 'config');
echo $config->Datbase->AccessSettings->Username; // prints "myDBUsername"
echo $config->Datbase->AccessSettings->Password; // prints "myDBPassword"

To edit and save your config you would use the following:

$config->Database->AccessSettings->Password = "foobar";
$writer = new Zend_Config_Writer_Ini(array('config'   => $config,
                                           'filename' => 'config.ini'));
$writer->write();

Edit

Not really sure why people are voting this down based on vog's misguided comments. It is very simple to make this writable by multiple persons by using an exclusive lock. Zend_Config_Writer uses file_put_contents to do it's writing, which has always supported the the LOCK_EX flag, which exclusively locks a file for writing. When using this flag, you cannot have multiple writers attempting to update the file at the same time.

To use this flag with Zend_Config_Writer it's as simple as follows:

$writer = new Zend_Config_Writer_Ini(array('config'   => $config,
                                           'filename' => 'config.ini'));
$writer->setExclusiveLock(true);
$writer->write();

An alternate syntax:

$writer = new Zend_Config_Writer_Ini();
$writer->write('config.ini', $config, true); // 3rd parameter is $exclusiveLock
hobodave
This will horribly fail on parallel access by multiple web clients.
vog
@vog: that's what caching is for.
hobodave
Also, it is assumed that *ANY* production PHP site is using some type of bytecode cache which provides a user cache, such as APC.
hobodave
Of course I meant parallel write access.
vog
"Settings will not be updated/added/removed very often." To vote me down for this is silly. We don't even know that this *is* a web application, nor that it will support multiple clients.
hobodave
There's a difference between "parallel writes cleanly overwrite each other" and "parallel writes leave a mess which can't be read in anymore". Although the first variant might be acceptable, the second one definitely isn't. However, the second scenario is possible since Zend_Config_Writer_Ini::write() is not atomic. Introducing such a race condition into a web application is negligent, and _that's_ my reason for voting down this dangerous approach. It is nothing personally against you, hobodave.
vog
Who said anything about a web application? How do you know he will allow multiple users access to write to this file? It's simple to implement this if that is his desire.
hobodave
Sorry, I should have clarified in my question that this will be a web application. To begin with it will only allow one user to write to the file. However, at some point I may change it to allow a select number (although not many) of users to edit the file. So I would like to know how to safely allow a couple users to write to this file. Is this possible using Zend_Config_Ini?
Brian
@vog: Your comments are misinformed, and wrong. @Brian: I updated my answer above, yes it is possible.
hobodave
@hobodave: thanks for all your help with this question! Zend_Config_Ini appears to do exactly what I want, and it looks like when I strip just that from the Zend Framework it is only like 5 files.
Brian
@Brian: Glad to have helped :-D
hobodave
A: 

If you are willing to drop in a library, you could use Spyc and have your configuration in a YAML file.

You could also use PHP's support for SQLite which would mean your database is just a file so no need for a DB server.

Nathan
A: 

DBM files may not be a bad idea. PHP has built in support for the various DBM-file varieties:

http://www.php.net/manual/en/book.dba.php

Rafe