How to Update an Ini File with PHP

PHP change only one value inside ini file

Got it fixed like this

  $filepath = 'config.ini';

$data = @parse_ini_file("config.ini");
$data['reinstall']='1';
//update ini file, call function
function update_ini_file($data, $filepath) {
$content = "";
//parse the ini file to get the sections
//parse the ini file using default parse_ini_file() PHP function
$parsed_ini = parse_ini_file($filepath, true);
foreach($data as $section => $values){
if($section === "submit"){
continue;
}
$content .= $section ."=". $values . "\n";
}
//write it into file
if (!$handle = fopen($filepath, 'w')) {
return false;
}
$success = fwrite($handle, $content);
fclose($handle);
}
update_ini_file($data, $filepath);
header('location: '.ROOT_PATH.'/');

Writing values to INI file

I'll try to explain first why your code doesn't work, compared to the other.

Your inifile-array is build up of a nested array, $array[section][item] = value. The first dimension has the section names. The second dimension is the name of the items in the sections. So $fbsettingsDB["location"] contains an array of items, of which "value" is one.

Implode doesn't check if the array is nested. It just takes the first dimension (the sections) and tries to treat their values as a string. Since those values are actually arrays of items, PHP just converts that to the text 'array'.

Apart from that, you can't just implode the whole array. Section names should be enclosed in square brackets, so there is a little more work to do in that regard too.

If you check the solution in the answer you referred to, you'll see that it contains a loop which takes care of the first layer, the sections.
The array of items of each section is converted separately with implode, which is then prefixed by the section name in square brackets, and the whole lot is appended to the end result.

So, your intention here: You don't want to set a value and write it back to file at once, but update multiple values and only write the end result to disk. Well, fortunately the function doesn't have to be atomic. It already performs three separate actions: loading from disk, modifying the data, and serializing it back to disk. Let's see if those can be isolated in separate functions:

Read the data. Well, hardly worth to make a function, but it may make your application somewhat more consistent if you use the same naming et cetera in a collection of related functions.

Note: I just wrote these from scratch. No PHP at hand to test, so they might contain minor syntactical errors.

So here it is:

// Loads ini file data
function config_read($config_file) {
return parse_ini_file($config_file, true);
}

Setting the config in the loaded data. Again, hardly worth to have a function, but it adds readability and hides how exactly the ini file data is built up, so you don't have to worry about implementation details when using it. Note that the array is passed by reference. The array you specify is updated. The function doesn't return a value.

// Update a setting in loaded inifile data
function config_set(&$config_data, $section, $key, $value) {
$config_data[$section][$key] = $value;
}

Then writing it:

// Serializes inifile config data back to disk.
function config_write($config_data, $config_file) {
$new_content = '';
foreach ($config_data as $section => $section_content) {
$section_content = array_map(function($value, $key) {
return "$key=$value";
}, array_values($section_content), array_keys($section_content));
$section_content = implode("\n", $section_content);
$new_content .= "[$section]\n$section_content\n";
}
file_put_contents($config_file, $new_content);
}

Note that so far I didn't modify any of the code. I just wrapped it in separate functions. If you like, you could even call those functions in another function, so you still got the shorthand to write everything to disk at once. You'll have the original functionality, but without having duplicate code:

// Short-hand function for updating a single config value in a file.
function config_set_file($config_file, $section, $key, $value) {
$config_data = config_read($config_file);
config_set($config_data, $section, $key, $value)
config_write($config_file, $section, $key, $value);
}

So, now you got this collection of functions, you can decide which to use based on the situation. If you just want to update a single value, you might as well write this:

config_set_file("location.ini", "id", "value", $_POST['fbconfigid']);

But if you have multiple configs to set, you can do this:

// Load
$config_data = config_read("location.ini");
// Set multiple values
config_set($config_data, "id", "value", $_POST['fbconfigid']);
config_set($config_data, "location", "value", $_POST['something']);
config_set($config_data, "result", "value", $_POST['somethingelse']);
// Save
config_write($config_data, $config_file);

I can imagine you can add other shorthands, like config_set_array_file, which you could call like this.. I'll leave the implementation of this one to you for exercise. ;)

array_config_set_file($config_file, array(
"id" => $_POST['fbconfigid'],
"location" => $_POST['something'],
"result" => $_POST['somethingelse']));

And after that, you can poor all this into an IniFile class to make it even nicer. :)

How can I edit the content of a ini file?

As an alternative, you could just use file() instead. This just loads it up into array form, no need to explode. Then after that, you just loop the elements, if the desired needle is found, overwrite it, the write the file again:

$data = file('sc_serv.conf', FILE_IGNORE_NEW_LINES); // load file into an array
$find = 'streamrelayurl_2='; // needle
$new_value = 'http://www.whateverurl.com'; // new value
foreach($data as &$line) {
if(strpos($line, 'streamrelayurl_2=') !== false) { // if found
$line = $find . $new_value; // overwrite
break; // stop, no need to go further
}
}
file_put_contents('sc_serv.conf', implode("\n", $data)); // compound into string again and write

PHP Add to key in ini file

You could add this condition to check if there is a value inside "color" (key section) and append new value accordingly :

if (empty($config_data[$section][$key])) {
$config_data[$section][$key] = $value;
} else {
$config_data[$section][$key] .= ',' . $value;
}

Full code :

function config_set($config_file, $section, $key, $value) {
$config_data = parse_ini_file($config_file, true);
if (empty($config_data[$section][$key])) {
$config_data[$section][$key] = $value;
} else {
$config_data[$section][$key] .= ',' . $value;
}
$new_content = '';
foreach ($config_data as $section => $section_content) {
$section_content = array_map(function($value, $key) {
return "$key=$value";
}, array_values($section_content), array_keys($section_content));
$section_content = implode("\n", $section_content);
$new_content .= "[$section]\n$section_content\n";
}
file_put_contents($config_file, $new_content);
}

How to change a 'php.ini' setting in a PHP file

The reason why error_reporting did work not is you set its value to the following string. 'E_WARNING ^ E_NOTICE ^ E_DEPRECATED'. But it should not be a string. E_* values are PHP constants and should be used outside quotes like:

ini_set('error_reporting', E_WARNING ^ E_NOTICE ^ E_DEPRECATED);

Also you are using binary XOR (^) between these constants, which is unusual. The suggested value for a production environments is to use E_ALL alone, for debugging. If you want all errors except E_DEPRECATED, you can use E_ALL & ~E_DEPRECATED.

Some PHP settings cannot be changed with ini_set. You can check the PHP documentation for which variables allow setting on the file level. For example, max_file_uploads is only changeable from the php.ini file (documentation).

How to read and write to an ini file with PHP

The PEAR Config_Lite package can do almost all the work (both reading and writing) for you super-easily. Check it out here: http://pear.php.net/package/Config_Lite



Related Topics



Leave a reply



Submit