|
|
 |
parse_ini_file (PHP 4, PHP 5) parse_ini_file -- Parse a configuration file Descriptionarray parse_ini_file ( string filename [, bool process_sections] )
parse_ini_file() loads in the
ini file specified in filename,
and returns the settings in it in an associative array.
By setting the last process_sections
parameter to TRUE, you get a multidimensional array, with
the section names and settings included. The default
for process_sections is FALSE
Note:
This function has nothing to do with the
php.ini file. It is already processed,
the time you run your script. This function can be used to
read in your own application's configuration files.
Note:
If a value in the ini file contains any non-alphanumeric
characters it needs to be enclosed in double-quotes (").
Note:
As of PHP 5.0 this function also handles new lines in values.
Note:
There are reserved words which must not be used as keys for
ini files. These include: null, yes, no, true, and false.
The structure of the ini file is similar to that of
the php.ini's.
Constants may also be parsed
in the ini file so if you define a constant as an ini value before
running parse_ini_file(), it will be integrated into
the results. Only ini values are evaluated. For example:
Example 1. Contents of sample.ini ; 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" |
|
Example 2. parse_ini_file() example |
<?php
define('BIRD', 'Dodo bird');
$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);
?>
|
Would produce:
Array
(
[one] => 1
[five] => 5
[animal] => Dodo bird
[path] => /usr/local/bin
[URL] => http://www.example.com/~username
)
Array
(
[first_section] => Array
(
[one] => 1
[five] => 5
[animal] = Dodo bird
)
[second_section] => Array
(
[path] => /usr/local/bin
[URL] => http://www.example.com/~username
)
) |
|
Keys and section names consisting from numbers are evaluated as PHP
integers thus numbers
starting by 0 are evaluated as octals and numbers starting by 0x are
evaluated as hexadecimals.
User Contributed Notes
parse_ini_file
alex at NO_SPAM_PLEASE_sourcelibre dot com
16-Mar-2005 04:07
Note these will be converted to '1' and '0'
[section]
foo = yes
bar = no
Therefore, they need to be put between brackets if you want the value to be 'yes' and 'no'.
sly at noiretblanc dot org
08-Mar-2005 10:57
Be careful with the string "none", for example if you want to save a CSS border-style in your config.ini file :
[style]
borderstyle=none
will return:
'style' => array ( 'borderstyle' => '' )
and not
'style' => array ( 'borderstyle' => 'none' )
The solution is to quote the string none :
[style]
borderstyle="none"
hoc at notmail dot com
31-Jan-2005 07:29
to phpcoder at cyberpimp dot pimpdomain dot com:
thx for the read/write ini functions, they work like a charm ...
except for that one small (easy to find) substr-bug in the readINIfile-function:
counting with substr starts from 0, not 1, so
<?php
if (substr($value, 1, 1) == '"' && ...
?>
should be ...
<?php
if (substr($value, 0, 1) == '"' && ...
?>
nospam_phpnet at scovetta dot com
17-Jan-2005 06:21
As a Java programmer, I find PHPs lack of handing of multi-line ".properties" files a bit of a pain. I didn't see PEAR::Config handle this, so I hacked together a quick Properties class. This is by no means complete. It works for me, but I'm sure that someone can improve it. I'm also not an expert in PHP, so it may look like a kludge. Anyway, here it is:
<?php
class Properties {
var $properties;
var $keyValueSeparators = "=: \t\r\n";
var $whiteSpaceChars = " \t\r\n";
function Properties($file = null) {
$this->properties = array();
if ($file) {
$this->load($file);
}
}
function set_property( $key, $value ) {
$this->properties[$key] = $value;
}
function get_property( $key ) {
return $this->properties[$key];
}
function load( $file ) {
$lines = file($file);
$lc = 0;
$cont = false;
foreach ($lines as $line) {
if (!$cont) {
$line = ltrim($line, $this->whiteSpaceChars);
$key = $this->findFirstIn($line, $this->keyValueSeparators);
if ($key === false)
continue;
$value = substr($line, $key+2);
$value = trim($value, $this->whiteSpaceChars);
$key = substr($line, 0, $key+1);
$key = trim($key, $this->whiteSpaceChars);
if (substr($value, strlen($value)-1, 1) === '\\') {
$value = substr($value, 0, strlen($value)-1);
$cont = true;
} else {
$this->properties[$key] = $value;
}
} else {
$line = trim($line, $this->whiteSpaceChars);
if (substr($line, strlen($line)-1, 1) === '\\') {
$value .= substr($line, 0, strlen($line)-1);
} else {
$cont = false;
$value .= $line;
$this->properties[$key] = $value;
}
}
}
}
function continueLine($line) {
$slashCount = 0;
$index = strlen($line) - 1;
while (($index >= 0) && (substr($line, $index--, 1) == '\\'))
$slashCount++;
return ($slashCount % 2 == 1);
}
function findFirstIn( $txt, $choices, $start = null)
{
$pos = -1;
$arr = array();
for ($i=0; $i<strlen($choices); $i++) {
array_push($arr, substr($choices, $i, 1));
}
foreach( $arr as $v ) {
$p = strpos( $txt, $v, $start );
if ($p===FALSE)
continue;
if (($p<$pos)||($pos==-1))
$pos = $p;
}
return $pos;
}
function toArray() {
return $this->properties;
}
}
?>
phpcoder at cyberpimp dot pimpdomain dot com
13-Jan-2005 03:31
Here's a much better way of reading and writing INI files. (much fewer character restrictions, automatic comment header, binary safe, etc.)
<?php
function readINIfile ($filename, $commentchar) {
$array1 = file($filename);
$section = '';
foreach ($array1 as $filedata) {
$dataline = trim($filedata);
$firstchar = substr($dataline, 0, 1);
if ($firstchar!=$commentchar && $dataline!='') {
if ($firstchar == '[' && substr($dataline, -1, 1) == ']') {
$section = strtolower(substr($dataline, 1, -1));
}else{
$delimiter = strpos($dataline, '=');
if ($delimiter > 0) {
$key = strtolower(trim(substr($dataline, 0, $delimiter)));
$value = trim(substr($dataline, $delimiter + 1));
if (substr($value, 1, 1) == '"' && substr($value, -1, 1) == '"') { $value = substr($value, 1, -1); }
$array2[$section][$key] = stripcslashes($value);
}else{
$array2[$section][strtolower(trim($dataline))]='';
}
}
}else{
}
}
return $array2;
}
function writeINIfile ($filename, $array1, $commentchar, $commenttext) {
$handle = fopen($filename, 'wb');
if ($commenttext!='') {
$comtext = $commentchar.
str_replace($commentchar, "\r\n".$commentchar,
str_replace ("\r", $commentchar,
str_replace("\n", $commentchar,
str_replace("\n\r", $commentchar,
str_replace("\r\n", $commentchar, $commenttext)
)
)
)
)
;
if (substr($comtext, -1, 1)==$commentchar && substr($comtext, -1, 1)!=$commentchar) {
$comtext = substr($comtext, 0, -1);
}
fwrite ($handle, $comtext."\r\n");
}
foreach ($array1 as $sections => $items) {
if (isset($section)) { fwrite ($handle, "\r\n"); }
$section = ucfirst(preg_replace('/[\0-\37]|\177/', "-", $sections));
fwrite ($handle, "[".$section."]\r\n");
foreach ($items as $keys => $values) {
$key = ucfirst(preg_replace('/[\0-\37]|=|\177/', "-", $keys));
if (substr($key, 0, 1)==$commentchar) { $key = '-'.substr($key, 1); }
$value = ucfirst(addcslashes($values,''));
fwrite ($handle, ' '.$key.' = "'.$value."\"\r\n");
}
}
fclose($handle);
}
?>
georg at linux dot ee
09-Jan-2005 04:15
<?php
function ns_ini_lcrefs(& $arr) {
foreach (array_keys($arr) as $_k) {
if (is_array($arr[$_k]) && !isset($arr[$_k]['_ns_ini_lcrefs']))
ns_ini_lcrefs($arr[$_k]);
if (($_lc_k = strtolower($_k)) != $_k)
$arr[$_lc_k] =& $arr[$_k];
}
$arr['_ns_ini_lcrefs'] = true;
} ?>
Nick Deppe
19-Oct-2004 09:03
I just noticed that the code I wrote before had an error in it. I have the fix posted here:
That is what happens when you don't error check the code first. Duh.
Here is yet another version of write_ini_file. This version takes data types into account. If the file is numeric or boolean, the value is written in the ini file without quotes. Else it will be written with quotes.
Please note that if a string that CAN be converted into a number WILL be converted into a number because I used the is_numeric function. If you want to make sure that the data type is strictly preserved, use the is_integer and is_double functions in place of the is_numeric function.
<?php
if(!function_exists('write_ini_file')) {
function write_ini_file($path, $assoc_array) {
foreach($assoc_array as $key => $item) {
if(is_array($item)) {
$content .= "\n[{$key}]\n";
foreach ($item as $key2 => $item2) {
if(is_numeric($item2) || is_bool($item2))
$content .= "{$key2} = {$item2}\n";
else
$content .= "{$key2} = \"{$item2}\"\n";
}
} else {
if(is_numeric($item) || is_bool($item))
$content .= "{$key} = {$item}\n";
else
$content .= "{$key} = \"{$item}\"\n";
}
}
if(!$handle = fopen($path, 'w')) {
return false;
}
if(!fwrite($handle, $content)) {
return false;
}
fclose($handle);
return true;
}
}
?>
bkw at weisshuhn dot de
27-Sep-2004 04:56
Beware that currently you cannot have a closing square bracket (]) in any of the values if you are using sections, no matter how you quote.
See: http://bugs.php.net/bug.php?id=28804
This bug also seems to affect PEAR::Config.
tomasz.frelik(at)enzo.pl
08-Aug-2004 06:49
Here is a better version of write_ini_file() function, which can found below. This version allows you to use sections and still have "global" variables in ini file. The structure of resulting ini file mirrors the structure of the array passed to the function. You can have sections or no, it's up to you.
function write_ini_file($path, $assoc_array) {
foreach ($assoc_array as $key => $item) {
if (is_array($item)) {
$content .= "\n[$key]\n";
foreach ($item as $key2 => $item2) {
$content .= "$key2 = \"$item2\"\n";
}
} else {
$content .= "$key = \"$item\"\n";
}
}
if (!$handle = fopen($path, 'w')) {
return false;
}
if (!fwrite($handle, $content)) {
return false;
}
fclose($handle);
return true;
}
hfuecks at phppatterns dot com
15-Jul-2004 10:20
parse_ini_file seems to have changed it's signature between PHP 4.3.x and PHP 5.0.0 (can't find any relevant changelog / cvs entries referring to this).
In PHP 4.3.x and below return value was a boolean FALSE if the ini file could not be found. With PHP 5.0.0 the return value is an empty array if the file is not found.
php at isaacschlueter dot com
22-Jun-2004 01:47
Even better than putting the <?php at the head of the file is to do something like this:
--config.ini.php--
; <?php die( 'Please do not access this page directly.' ); ?>
; This is the settings page, do not modify the above line.
setting = value
...
Jomel (k95vz5f02 AT sneakemail DOT com)
19-Jun-2004 10:02
based entirely on LIU student's code (thanks), here's a write_ini_file function you can use whether or not the array you are writing is sorted into sections.
It is designed so that $arr1 equals $arr2 in both the cases below, using sections:
<?php
$arr1 = parse_ini_file($filename, true);
write_ini_file(parse_ini_file($filename, true), $filename, true);
$arr2 = parse_ini_file($filename, true);
?>
and without sections:
<?php
$arr1 = parse_ini_file($filename);
write_ini_file(parse_ini_file($filename), $filename);
$arr2 = parse_ini_file($filename);
?>
i.e. files written using write_ini_file will be semantically identical (as far as parse_ini_file can see) to the originals.
Here is the code:
<?php
if (!function_exists('write_ini_file')) {
function write_ini_file($assoc_arr, $path, $has_sections=FALSE) {
$content = "";
if ($has_sections) {
foreach ($assoc_arr as $key=>$elem) {
$content .= "[".$key."]\n";
foreach ($elem as $key2=>$elem2) {
$content .= $key2." = \"".$elem2."\"\n";
}
}
}
else {
foreach ($assoc_arr as $key=>$elem) {
$content .= $key." = \"".$elem."\"\n";
}
}
if (!$handle = fopen($path, 'w')) {
return false;
}
if (!fwrite($handle, $content)) {
return false;
}
fclose($handle);
return true;
}
}
?>
Incidentally I wrapped it inside an if (!function_exists(...)) block so you can just put this wherever it's needed in your code without having to worry about it being declared several times.
Warning: if you read an ini file then write it using <?php write_ini_file(parse_ini_file($fname), $fname); ?>, any sections will obviously be lost.
Note also: unquoted values will be quoted and varname=true will become varname = "1" when writing an ini file back to itself using <?php write_ini_file(parse_ini_file($fname, true), $fname, true); ?> or <?php write_ini_file(parse_ini_file($fname), $fname); ?>. This should make no difference, but it might cause the types of the variables to change in case you plan on using === or !== comparisions.
forceone at justduck.net
14-Jun-2004 10:00
A better version of parse_ini_str that takes into account values that are named the same.
<?php
function parse_ini_str($Str,$ProcessSections = TRUE) {
$Section = NULL;
$Data = array();
if ($Temp = strtok($Str,"\r\n")) {
do {
switch ($Temp{0}) {
case ';':
case '#':
break;
case '[':
if (!$ProcessSections) {
break;
}
$Pos = strpos($Temp,'[');
$Section = substr($Temp,$Pos+1,strpos($Temp,']',$Pos)-1);
$Data[$Section] = array();
break;
default:
$Pos = strpos($Temp,'=');
if ($Pos === FALSE) {
break;
}
$Value = array();
$Value["NAME"] = trim(substr($Temp,0,$Pos));
$Value["VALUE"] = trim(substr($Temp,$Pos+1),' "');
if ($ProcessSections) {
$Data[$Section][] = $Value;
}
else {
$Data[] = $Value;
}
break;
}
} while ($Temp = strtok("\r\n"));
}
return $Data;
}
?>
Example:
[Files]
File=File1
File=File2
would return:
array (
'Files' => array (
0 => array (
'NAME' => 'File',
'VALUE' => File1',
),
1 => array (
'NAME' => 'File',
'VALUE' => 'File2',
),
),
)
LIU student
19-Mar-2004 08:08
[Editor's note: The fwrite()-line should look like: "if (fwrite($handle, $content) === false) {" to avoid returning false when the array is empty --victor@php.net]
function writeIni($assoc_arr, $path){
$content = "";
foreach ( $assoc_arr as $key=>$elem ){
$content .= "[".$key."]\n";
foreach ( $elem as $key2=>$elem2){
$content .= $key2." = \"".$elem2."\"\n";
}
}
if (!$handle = fopen($path, 'w')) {
return false;
}
if (!fwrite($handle, $content)) {
return false;
}
fclose($handle);
return true;
}
waikeatNOSPAM at archerlogic dot com
09-Nov-2003 08:37
rus dot grafx at usa dot net
10-Oct-2003 08:15
Instead of using parse_ini_file() function I would recommend to use PEAR's Config package which is MUCH more flexible (assuming that you don't mind using PEAR and OOP). Have a closer look at http://pear.php.net/package/Config
dshearin at excite dot com
19-Jun-2003 10:47
I found another pitfall to watch out for. The key (to the left of the equal sign) can't be the same as one of the predefined values, like yes, no, on, off, etc. I was working on a script that read in an ini file that matched the country codes of top level domains to the full name of the country. I kept getting a parse error everytime it got to the entry for Norway ("no"). I fixed the problem by sticking a dot in front of each of the country codes.
10-May-2003 06:05
If your configuration file holds any sensitive information (such as database login details), remember NOT to place it within your document root folder! A common mistake is to replace config.inc.php files, which are formatted in PHP:
<?php
$database['host'] = 'localhost';
?>
With config.ini files which are written in plain text:
[database]
host = localhost
The file config.ini can be read by anyone who knows where it's located, if it's under your document root folder. Remember to place it above!
kieran dot huggins at rogers dot com
07-Jan-2003 12:24
Just a quick note for all those running into trouble escaping double quotes:
I got around this by "base64_encode()"-ing my content on the way in to the ini file, and "base64_decode()"-ing on the way out.
Because base64 uses the "=" sign, you will have to encapsulate the entire value in double quotes so the line looks like this:
varname = "TmlhZ2FyYSBGYWxscywgT04="
When base64'd, your strings will retain all \n, \t...etc... URL's retain everything perfectly :-)
I hope some of you find this useful!
Cheers, Kieran
fbeyer at clickhand dot de
29-Nov-2002 11:37
Besides the features mentioned above (eg. core constants, booleans), you can also access user-defined constants in ini files! This is handy if you want to create a bit-field, for example:
+++ PHP +++
// Define pizza toppings
define('PIZZA_HAM', 1);
define('PIZZA_PINEAPPLE', 2);
define('PIZZA_ONION', 4);
define('PIZZA_MOZARELLA', 8);
define('PIZZA_GARLIC', 16);
// Read predefined pizzas
$pizzas = parse_ini_file('pizzas.ini');
if ($pizzas[$user_pizza] & PIZZA_ONION) {
// Add onions to the pizza
}
+++ INI +++
[pizzas]
; Define pizzas
hawaii = PIZZA_HAM | PIZZA_PINEAPPLE
stinky = PIZZA_ONION | PIZZA_GARLIC
bob at kludgebox dot com
26-Mar-2002 12:27
And for the extra-paranoid like myself, add a rule into your httpd.conf file so that *.ini (or *.inc) in my case can't be sent to a browser:
<Files *.inc>
Order deny,allow
Deny from all
</Files>
JoshuaStarr at aelana dot com
14-Jan-2002 09:41
It should be noted that in all of our attempts you cannot escape a double quote in the value when read with the parse_ini_file() function.
;============================
; Example Configuration File
;============================
[category]
title = "Best Scripting Language"
desc = "See <a href=\"http://www.php.net/\">PHP</a>!"
If this file is read by parse_ini_file() the link value will not be set because of the escaped double quotes.
| |