Parsing INI Files With PHP
Introduction
Some people like to use .ini
files for configuration settings. PHP can parse these ini files with the
parse_ini_file function,
but unfortunately it's default settings are a bit rubbish and this tutorial will explain why and how to fix it.
Setup
All of the examples here will be using the following example config.ini
configuration file.
global_decimal_value = 0.25
[Falses]
false_string = "False"
false_bool = False
false_empty_string = ""
false_int = 0
[Trues]
true_string = "True"
true_bool = True
true_int = 1
As you can see, we have a mixture of decimals/floats, strings, booleans, and integers, as well as two "sections" named "Falses" and "Trues".
Basic Parsing
If you were to use the parse the ini file like so:
$data = parse_ini_file(__DIR__ . '/config.ini');
var_dump($data);
Then you would get the following output:
array(8) {
["global_decimal_value"]=>
string(4) "0.25"
["false_string"]=>
string(5) "False"
["false_bool"]=>
string(0) ""
["false_empty_string"]=>
string(0) ""
["false_int"]=>
string(1) "0"
["true_string"]=>
string(4) "True"
["true_bool"]=>
string(1) "1"
["true_int"]=>
string(1) "1"
}
As you can see, everything has been returned as a string value, and the sectioning has been completely lost.
Restore Sectioning
Luckily, you can easily restore the sectioning, by adding a simple parameter like so (I'm using named parameters to make things straightforward).
$data = parse_ini_file(
filename: __DIR__ . '/config.ini',
process_sections: true,
);
var_dump($data);
This will output the following:
array(3) {
["global_decimal_value"]=>
string(4) "0.25"
["Falses"]=>
array(4) {
["false_string"]=>
string(5) "False"
["false_bool"]=>
string(0) ""
["false_empty_string"]=>
string(0) ""
["false_int"]=>
string(1) "0"
}
["Trues"]=>
array(3) {
["true_string"]=>
string(4) "True"
["true_bool"]=>
string(1) "1"
["true_int"]=>
string(1) "1"
}
}
As you can see, the global vars are held in name/value pairs without any nesting, and the subsections can be accessed through nested indexed arrays. However, we have still lost all of our typings, such that integers and booleans are returned as strings.
Restore Types
One can optionally specify a scanner_mode
which as of PHP 5.6.1 (god help you if you are running a PHP version lower than this),
has the INI_SCANNER_TYPED
optional value, which will preserve the types.
If you were to run:
$data = parse_ini_file(
filename: __DIR__ . '/config.ini',
process_sections: true,
scanner_mode: INI_SCANNER_TYPED
);
var_dump($data);
Then it would output:
array(3) {
["global_decimal_value"]=>
float(0.25)
["Falses"]=>
array(4) {
["false_string"]=>
string(5) "False"
["false_bool"]=>
bool(false)
["false_empty_string"]=>
string(0) ""
["false_int"]=>
int(0)
}
["Trues"]=>
array(3) {
["true_string"]=>
string(4) "True"
["true_bool"]=>
bool(true)
["true_int"]=>
int(1)
}
}
As you can see, all of the types camee through correctly.
Conclusion
Whenever parsing INI files, make sure to remember to specify both the process_sections
and scanner_mode
optional parameters like so:
parse_ini_file(
filename: __DIR__ . '/config.ini',
process_sections: true,
scanner_mode: INI_SCANNER_TYPED
);
Frankly, it seems so obvious that I'm amazed their default values are not set to this, but I guess it's to prevent accidentally breaking legacy code with a PHP version update (e.g. backwards compatibility).
References
First published: 2nd May 2024