Reading and Writing INI files

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Reading and Writing INI files

Post by Maugrim_The_Reaper »

I started work a few days back on a Settings class group for a project (another developer requested it to do some work on a separate area that required working with Settings). Anyways, the structure is simple enough as are the classes. My main question relates to the INI format which I've never worked with much in the past.

Are there any special special requirements to working with INI files other than the basics? What sort of data are INI files good and bad at storing? The current class seems to work okay for the moment, but my knowledge of INI syntax quirks is non existent.

Code: Select all

abstract class Parth_Settings {

	protected $settings = array();

	protected function __construct() {}

	public function get($var) {
		$pieces = explode('.', $var);
		switch(count($pieces))
		{
			case 2:
				return $this->settings[$pieces[0]][$pieces[1]];
				break;
			case 1:
				return $this->settings[$pieces[0]];
				break;
			default:
				return null;
		}
	}

	public function set($var, $value) {
		$pieces = explode('.', $var);
		switch(count($pieces))
		{
			case 2:
				$this->settings[$pieces[0]][$pieces[1]] = $value;
				break;
			case 1:
				$this->settings[$pieces[0]] = $value;
				break;
		}
	}

	public abstract function import($data);

	public abstract function export();

	protected function define_phpeol() {
		if (!defined('PHP_EOL'))
		{
			switch (strtoupper(substr(PHP_OS, 0, 3)))
				{
				case 'WIN':
					define('PHP_EOL', "\r\n"); // Windows
					break;
				case 'DAR':
					define('PHP_EOL', "\r"); // Mac OS
					break;
				default:
					define('PHP_EOL', "\n"); // *nix
			}
		}
	}

}

class Parth_INISettings extends Parth_Settings  {

	public function __construct() {}

	public function import($file) {
		if(!file_exists($file))
		{
			return false;
		}
		$this->settings = parse_ini_file($file, true);
	}

	public function export() {
		$this->define_phpeol();
		$ini_nosections = '';
		$ini_sections = '';
		foreach ($this->settings as $key=>$elem)
		{
			if(is_array($elem))
			{
				$ini_sections .= PHP_EOL . PHP_EOL . "[" . $key . "]" . PHP_EOL;
				foreach($elem as $name=>$value)
				{
					$ini_sections .= PHP_EOL . $name . ' = ' . $value;
				}
			}
			else
			{
				$ini_nosections .= PHP_EOL . $key . ' = ' . $elem;
			}
		}
		$file_content = $ini_nosections . $ini_sections;
		return $file_content;
	}

}
Unit Tests:

settings.ini

Code: Select all

; Sample INI file for Unit Testing of Parth_INISettings class

; name has no section [], added to settings array directly

name = partholan
type = framework

; app is a section, and forms a new sub array of settings array

[app]
type = library

Code: Select all

class Test_INIArraySettings extends UnitTestCase {

	private $inifile;

	public function __construct() {
		$this->UnitTestCase('INISettings Test');
		$this->inifile = TESTROOT . 'Other/settings.ini';
	}

	public function testBasics() {
		$settings = new Parth_INISettings();
		$settings->import($this->inifile);
		$this->assertEqual($settings->get('name'), 'partholan');
		$this->assertEqual($settings->get('app.type'), 'library');
		$settings->set('app.author', 'me');
		$settings->set('user', 'meagain');
		$this->assertEqual($settings->get('app.author'), 'me');
		$this->assertEqual($settings->get('user'), 'meagain');
		$export = $settings->export();
		$this->assertEqual(implode('', explode(PHP_EOL, $export)), $this->expectedExport());
	}

	// expected export file contents with all newlines removed
	private function expectedExport() {
		$ini = "name = partholantype = frameworkuser = meagain[app]type = libraryauthor = me";
		return $ini;
	}

}
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

Incase you haven't looked at it yet :)

http://en.wikipedia.org/wiki/INI_file
User avatar
johno
Forum Commoner
Posts: 36
Joined: Fri May 05, 2006 6:54 am
Location: Bratislava/Slovakia
Contact:

Post by johno »

User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

[quote=Maugrim_The_Reaper]

Code: Select all

public function import($file) {
                if(!file_exists($file))
                {
                        return false;
                }
                $this->settings = parse_ini_file($file, true);
        }
[/quote]

Got the PHP function ;)

I was just uncertain about the syntax supported by INI, and couldn't find a specification anywhere. Seems it's just informal (kind of odd). Hockey's link to Wikipedia had two unofficial specs, so I'm looking at those instead.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

Seems it's just informal (kind of odd)
Yea...it's alot like CSV...but considering the age of the file formats...it should come at no surprise...

I have bad memories of tinkering with INI files and not being able to get anything working after that...and having to reinstall :?

Unlike XML, CSV and INI were introduced at a time when cross platform wasn't really an issue and standards weren't a big deal...

Also, XML was invented for a reason, whereas I would bet that CSV and INI were just kind of adhoc hacks...

Stranger things have happened :P

Cheers :)
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

A couple of years ago i read 'The art of Unix Programming'...

The following section talks about a couple of alternatives: http://www.catb.org/esr/writings/taoup/ ... 05s02.html
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Thanks to everyone who helped create XML :).
Post Reply