0

Was just wondering if anyone had a good system for storing / updating dynamic settings in php?

What i mean by dynamic is settings that change automatically by other scripts.

Currently we use a system that basically file_get_contents our settings php file, treats that as a string, changes settings and file_put_contents the updated settings.

It works but its a bit dirty. Any other recommendations where we can store / modify / pull these settings from? Mysql is NOT an option, we want to avoid the extra queries.

As an added bonus, some system that can share this data over multiple servers as many of these settings are used across multiple boxes. But i suppose we can deal with that seperatly.

Thx!

AstroCB
  • 12,337
  • 20
  • 57
  • 73
anonymous-one
  • 14,454
  • 18
  • 60
  • 84
  • Why do you not want to use MySQL exactly? – Sjoerd Jul 20 '11 at 11:51
  • Would like to avoid the extra 10000000 or so daily queries. Yes they would hit the query cache 99.999% of the time but still we have a source base where many cron style scripts dont even mysql connect. – anonymous-one Jul 20 '11 at 11:56
  • I'm wondering, is reading a file using file_get_contents and parsing it (or whatever you do with it) is really less expensive than a MySql query? – nobody Jul 20 '11 at 12:20
  • This is only done on updates. Which occur once every few hours. Otherwise its included via include(... So reading wise its alot less expensive for sure. The changes are infrequent, very infrequent. – anonymous-one Jul 20 '11 at 12:23

5 Answers5

2

You really don't want to store dynamic data in files, particularly if its common data. PHP does not have the sophisticated file locking semantics to support this. If you know what you're doing you could implement your own advisory locaking system on top of PHP - but if you knew what you were doing you wouldn't be asking the question.

Mysql is NOT an option, we want to avoid the extra queries

Oh dear.

MySQL is probably the best option given the information you've provided. And if you've load problems on your database, trying to use different substrates for your data is not going to help.

Indeed, I would recommend implementing the storage and retrieval of values within a custom database bound session handler (and enabling sessions for all requests).

There are other tools you could use - nosql databases and memcache being obvious candidates - but they make less sense when you've already got a MySQL instance available.

(shared memory and the APC variable store have the same issues as file based storage)

symcbean
  • 47,736
  • 6
  • 59
  • 94
1

If you don't want to use MySql I think what you are doing right now is the best solution, any kind of properties/ini file writing system would be a lot more expensive and will not solve the concurrent access issues. To eliminate the issue I suggest you write the updated file to a temporary file in the same folder delete the old settings.php and rename the temp file to settings.php. there is still a small chance that a request be made just after settings.php is deleted and before temp file is renamed which can be handled by doing something like this when you include the file:

if( file_exists( 'settings.php' ) ) {
    include( 'settings.php' );
} else {
    /* ... wait 100 miliseconds or so and try again... do this a few times and then fail ... */
}

this should be quite safe.

nobody
  • 10,599
  • 4
  • 26
  • 43
  • the council is deciding on weather to go the mysql route. probably will tho. the reason i decided to tackle this now is because we need those settings to share between boxes. and mysql seams like the best way to do this. – anonymous-one Jul 20 '11 at 13:04
1

Things to keep in mind if you stick with a file-based approach:

Using a native parser

A parser written in C will most likely be quicker than one in PHP. The two options that spring to mind are

Use a settings.php file, that contains well-formed PHP code. One approach I've used in the past is having a file that looks like

<?php return
array(
'key' => 'value'
);

This file can be include-d one or more times, and the include statement will return the configuration array. When you're writing the new settings, use var_export() to get valid php code.

The other approach is using a settings.csv file. Read using fgetcsv(), write using fputcsv().

Avoiding "partial" saves

To avoid a partial file being read while the settings are being updated, first write the new settings to a temporary file, then move this file to the setting file location (preferrably using mv (1) on *nix).

Community
  • 1
  • 1
gnud
  • 77,584
  • 5
  • 64
  • 78
  • heads up: regarding using mv to prevent partial saves. this does work, but make sure the source AND target are on the same filesystem. or else the 'inode change' technique cannot be used. – anonymous-one Sep 05 '11 at 14:22
  • i voted this answer because we ended up leaving things as is, just implementing the mv method to avoid partial saves. – anonymous-one Sep 06 '11 at 10:48
0

I'd say ini files. parse_ini_file() (http://php.net/manual/en/function.parse-ini-file.php) is an excellent function which takes care of the reading and the answer to writing is right here: create ini file, write values in PHP

Community
  • 1
  • 1
Karl Laurentius Roos
  • 4,360
  • 1
  • 33
  • 42
  • 1
    Which is likely to go horribly wrong with concurrent access and frequent updates. :( – symcbean Jul 20 '11 at 12:05
  • So far this looks most promising. Similar to what we do now but looks like it would simplify things quite a bit. At least as far as store / update / retrieve goes. We can prolly deal with the sync over multiple servers seperatly. – anonymous-one Jul 20 '11 at 12:06
  • We have the same update issues with our manual file put contents method. A couple times a day php will syntax error because the file is mid write. Yes we tried the file put contents flag for locking to no avail. Sorry for lack of further detail at airport writing on phone. – anonymous-one Jul 20 '11 at 12:08
0

For this purpose we use this: http://projects.jgotti.net/projects/simplemvc/browse/trunk/includes/fx-conf.php it read and write to simple text files that contains key = values pairs.

parse_conf_file can load the confs as defined values or return an associative array of key values. Write_conf_file allow you to overwrite only the needed values by passing an array of key values as parameters.

If you have allow_url_fopen set to true then you can load the configuration file from another server without problem.

Hope this help

malko
  • 2,292
  • 18
  • 26