30

I've been looking around the official php documentation but I'm unable to find what I'm looking for.

http://php.net/manual/en/function.parse-ini-file.php

I just want a function to edit and read the value from the php ini file, for instance,

[default_colors]
sitebg = #F8F8F8
footerbg = #F8F8F8
link = #F8F8F8
url = #F8F8F8
bg = #F8F8F8
text = #F8F8F8
border = #F8F8F8

lu_link = #F8F8F8
lu_url = #F8F8F8
lu_bg = #F8F8F8
lu_text = #f505f5
lu_border = #F8F8F8
  1. How do I read the value belonging to "lu_link" or "footerbg"?
  2. How to I write a new value for these places?
Teoman Soygul
  • 25,584
  • 6
  • 69
  • 80
Joricam
  • 2,329
  • 4
  • 18
  • 14

6 Answers6

59

You can simply use parse_ini_file with PHP4/5.

$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);

Here is the doc: http://php.net/manual/en/function.parse-ini-file.php

To write back an array of objects back to the ini file, use below as a very fast & easy solution:

function write_php_ini($array, $file)
{
    $res = array();
    foreach($array as $key => $val)
    {
        if(is_array($val))
        {
            $res[] = "[$key]";
            foreach($val as $skey => $sval) $res[] = "$skey = ".(is_numeric($sval) ? $sval : '"'.$sval.'"');
        }
        else $res[] = "$key = ".(is_numeric($val) ? $val : '"'.$val.'"');
    }
    safefilerewrite($file, implode("\r\n", $res));
}

function safefilerewrite($fileName, $dataToSave)
{    if ($fp = fopen($fileName, 'w'))
    {
        $startTime = microtime(TRUE);
        do
        {            $canWrite = flock($fp, LOCK_EX);
           // If lock not obtained sleep for 0 - 100 milliseconds, to avoid collision and CPU load
           if(!$canWrite) usleep(round(rand(0, 100)*1000));
        } while ((!$canWrite)and((microtime(TRUE)-$startTime) < 5));

        //file was locked so now we can store information
        if ($canWrite)
        {            fwrite($fp, $dataToSave);
            flock($fp, LOCK_UN);
        }
        fclose($fp);
    }

}
JackLeEmmerdeur
  • 724
  • 11
  • 17
Teoman Soygul
  • 25,584
  • 6
  • 69
  • 80
  • thanks but I had already searched this and since I'm very new to php it is very confusign at a glance – Joricam Apr 17 '11 at 18:20
  • 3
    safefilerewrite is a user made function. If you go to the php doc listed in the answer and search the comments for safefilerewrite you will see one possible example. – K.B. Jan 30 '13 at 02:15
  • does it work with `[section1] lines [section2] lines` ? –  Sep 07 '17 at 13:05
13

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

cweiske
  • 30,033
  • 14
  • 133
  • 194
Winfield Trail
  • 5,535
  • 2
  • 27
  • 43
  • OMG this looks GREAT! but I'm very new to php and programming in general, what is PEAR? Whats is a framework? Will this work in my hosted site? – Joricam Apr 17 '11 at 18:02
  • ok I've got it instaled and downloaded the module and got it reading a ini file already :P Thanks. But can you teach me more about what is a framework and why did I had to install pear? Why is config_lite called a "module" ? I would really like to learn this the proper way please. – Joricam Apr 17 '11 at 18:20
  • Sure, no problem. Simply put, PEAR is a collection of "modules" - generalized, but purpose-built PHP code that's already been written for you, to automate and simplify numerous tasks. You had to install it separately because it's written and maintained by enthusiasts, and because the solutions it provides are too large and too specific to really make sense as part of the core PHP language. Config_lite is only one out of many, many modules; among them is the full Config module, which is like config_lite but with more features. – Winfield Trail Apr 17 '11 at 18:43
  • I have a big problem with saving the ini file, and I've tried this outised pear, it adds "" around keyvalues for keyvalues that where not wrapped around "". – Joricam Apr 17 '11 at 21:55
  • You can remove the containing quotes either with substr() or with a regex, for example: $data = preg_replace('/^\"(.*)\"$/','\${1}',$data); – Winfield Trail Apr 17 '11 at 22:02
  • 1
    Config_Lite is also available by composer (see [github](https://github.com/pear/Config_Lite)) – Andrey Bakharev Feb 24 '16 at 14:45
5

How about this:

 $key='option';
 $val='1.2.3.4.5';
 system("sed  -ie  's/\({$key}=\)\(.*\)/\1{$val}/' file.in");
5

Below is an implementation of write_ini_file() which PHP is currently lacking, it will create an almost identical (except comments) of the input:

  • Supports cross platform (PHP_EOL) new lines added between sections.
  • Handles both index and key value arrays.
  • Handles CONSTANT style values.
  • And file locking to stay consistent.

Source

<?php
if (!function_exists('write_ini_file')) {
    /**
     * Write an ini configuration file
     * 
     * @param string $file
     * @param array  $array
     * @return bool
     */
    function write_ini_file($file, $array = []) {
        // check first argument is string
        if (!is_string($file)) {
            throw new \InvalidArgumentException('Function argument 1 must be a string.');
        }

        // check second argument is array
        if (!is_array($array)) {
            throw new \InvalidArgumentException('Function argument 2 must be an array.');
        }

        // process array
        $data = array();
        foreach ($array as $key => $val) {
            if (is_array($val)) {
                $data[] = "[$key]";
                foreach ($val as $skey => $sval) {
                    if (is_array($sval)) {
                        foreach ($sval as $_skey => $_sval) {
                            if (is_numeric($_skey)) {
                                $data[] = $skey.'[] = '.(is_numeric($_sval) ? $_sval : (ctype_upper($_sval) ? $_sval : '"'.$_sval.'"'));
                            } else {
                                $data[] = $skey.'['.$_skey.'] = '.(is_numeric($_sval) ? $_sval : (ctype_upper($_sval) ? $_sval : '"'.$_sval.'"'));
                            }
                        }
                    } else {
                        $data[] = $skey.' = '.(is_numeric($sval) ? $sval : (ctype_upper($sval) ? $sval : '"'.$sval.'"'));
                    }
                }
            } else {
                $data[] = $key.' = '.(is_numeric($val) ? $val : (ctype_upper($val) ? $val : '"'.$val.'"'));
            }
            // empty line
            $data[] = null;
        }

        // open file pointer, init flock options
        $fp = fopen($file, 'w');
        $retries = 0;
        $max_retries = 100;

        if (!$fp) {
            return false;
        }

        // loop until get lock, or reach max retries
        do {
            if ($retries > 0) {
                usleep(rand(1, 5000));
            }
            $retries += 1;
        } while (!flock($fp, LOCK_EX) && $retries <= $max_retries);

        // couldn't get the lock
        if ($retries == $max_retries) {
            return false;
        }

        // got lock, write data
        fwrite($fp, implode(PHP_EOL, $data).PHP_EOL);

        // release lock
        flock($fp, LOCK_UN);
        fclose($fp);

        return true;
    }
}

Example input .ini file (taken from http://php.net/manual/en/function.parse-ini-file.php)

; 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"

[third_section]
phpversion[] = "5.0"
phpversion[] = "5.1"
phpversion[] = "5.2"
phpversion[] = "5.3"

urls[svn] = "http://svn.php.net"
urls[git] = "http://git.php.net"

Example usage:

// load ini file values into array
$config = parse_ini_file('config.ini', true);

// add some additional values
$config['main']['foobar'] = 'baz';
$config['main']['const']['a'] = 'UPPERCASE';
$config['main']['const']['b'] = 'UPPER_CASE WITH SPACE';
$config['main']['array'][] = 'Some Value';
$config['main']['array'][] = 'ADD';
$config['third_section']['urls']['docs'] = 'http://php.net';

// write ini file
write_ini_file('config.ini', $config);

Resulting .ini file:

[first_section]
one = 1
five = 5
animal = BIRD

[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"

[third_section]
phpversion[] = 5.0
phpversion[] = 5.1
phpversion[] = 5.2
phpversion[] = 5.3
urls[svn] = "http://svn.php.net"
urls[git] = "http://git.php.net"
urls[docs] = "http://php.net"

[main]
foobar = "baz"
const[a] = UPPERCASE
const[b] = "UPPER_CASE WITH SPACE"
array[] = "Some Value"
array[] = ADD
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
3

Here's a functional version that creates a string that can be written to a file.

function IniAsStr(array $a) : string
{
    return array_reduce(array_keys($a), function($str, $sectionName) use ($a) {
        $sub = $a[$sectionName];
        return $str . "[$sectionName]" . PHP_EOL .
            array_reduce(array_keys($sub), function($str, $key) use($sub) {
                return $str . $key . '=' . $sub[$key] . PHP_EOL;
            }) . PHP_EOL;
      });
}
Ted
  • 551
  • 1
  • 7
  • 16
1

Here is your function to read and write INI files with a category option!

If you provide multi dimensional array, you will have category in your INI file. Or basic array will allow you to read and write data fast.

See the comments and example below for details:

### PHP write_ini_file function to use with parse_ini_file: (choose one of the two example arrays below...)
$array = array('category' => array('color' => 'blue', 'size' => 'large'));
// $array = array('color' => 'red', 'size' => 'small');
function write_ini_file($array, $path) {
    unset($content, $arrayMulti);

    # See if the array input is multidimensional.
    foreach($array AS $arrayTest){
        if(is_array($arrayTest)) {
          $arrayMulti = true;
        }
    }

    # Use categories in the INI file for multidimensional array OR use basic INI file:
    if ($arrayMulti) {
        foreach ($array AS $key => $elem) {
            $content .= "[" . $key . "]\n";
            foreach ($elem AS $key2 => $elem2) {
                if (is_array($elem2)) {
                    for ($i = 0; $i < count($elem2); $i++) {
                        $content .= $key2 . "[] = \"" . $elem2[$i] . "\"\n";
                    }
                } else if ($elem2 == "") {
                    $content .= $key2 . " = \n";
                } else {
                    $content .= $key2 . " = \"" . $elem2 . "\"\n";
                }
            }
        }
    } else {
        foreach ($array AS $key2 => $elem2) {
            if (is_array($elem2)) {
                for ($i = 0; $i < count($elem2); $i++) {
                    $content .= $key2 . "[] = \"" . $elem2[$i] . "\"\n";
                }
            } else if ($elem2 == "") {
                $content .= $key2 . " = \n";
            } else {
                $content .= $key2 . " = \"" . $elem2 . "\"\n";
            }
        }
    }

    if (!$handle = fopen($path, 'w')) {
        return false;
    }
    if (!fwrite($handle, $content)) {
        return false;
    }
    fclose($handle);
    return true;
}

write_ini_file($array,'./data.ini');
$readData = parse_ini_file('./data.ini',true);
print_r($readData);
Tarik
  • 4,270
  • 38
  • 35