Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to parse config files in php

Status
Not open for further replies.

Dynamo3209

Programmer
Jan 2, 2003
57
0
0
US
I need a cross platform config file for a project using both perl and php. I need help in parsing a config file which could be used both by perl and php
the file structure for the config file I am thinking could be something like this
Option1:/var/abc/
Option2:{Option1}/bcd
Option3:{Option1}/efg
Option4:{Option3}/hij

so that if changes are made to any Options it will be reflected throughout the programme.
I am not sure whether this is something which could be done in php.
Appreciate any help in this matter.
Thanks,
Dynamo.
 
Of course you can do this in PHP.


If your config file were of the form:

Option1:/var/abc
Option2:{Option1}/bcd
Option3:{Option1}/efg
Option4:{Option3}/hij

(I've removed the slash from the end of the definition of Option1)

Then the following code:

Code:
<?php
$fh = fopen ('test_option.txt', 'r') or die('Could not open config file');

$option_matches = array();
$option_replacements = array();
while ($line = fgets($fh))
{
        $line = rtrim($line);
        $option_array = explode (':', $line);

        if (preg_match('/\{/', $option_array[1]))
        {
                $option_array[1] = preg_replace($option_matches,
$option_replacements, $option_array[1]);
        }

        $option_matches[] = '/\{' . $option_array[0] . '\}/';
        $option_replacements[] = $option_array[1];
}

fclose($fh);

foreach ($option_matches as $id => $value)
{
        $option_matches[$id] = str_replace('/\{', '', $option_matches[$id]);
        $option_matches[$id] = str_replace('\}/', '', $option_matches[$id]);
}

$options = array_combine ($option_matches, $option_replacements);

unset ($option_matches);
unset ($option_replacements);

print_r ($options);
?>

Returns:

Code:
Array
(
    [Option1] => /var/abc
    [Option2] => /var/abc/bcd
    [Option3] => /var/abc/efg
    [Option4] => /var/abc/efg/hij
)

Is that what you're looking for?


Want the best answers? Ask the best questions!

TANSTAAFL!!
 
Now that I think about it, my previous code post relies too heavily on the preg_* family of functions, which can impede performance.

Here's another version, which uses less resource-intensive functions:

Code:
function cleanup (&$item, $key)
{
        $item = str_replace('{', '', $item);
        $item = str_replace('}', '', $item);
}

$fh = fopen ('test_option.txt', 'r') or die('Could not open config file');

$option_matches = array();
$option_replacements = array();
while ($line = fgets($fh))
{
        $line = rtrim($line);
        $option_array = explode (':', $line);

        if (strstr($option_array[1], '{'))
        {
                $option_array[1] = str_replace($option_matches,
$option_replacements, $option_array[1]);

        }

        $option_matches[] = '{' . $option_array[0] . '}';
        $option_replacements[] = $option_array[1];
}

array_walk ($option_matches, 'cleanup');
$options = array_combine ($option_matches, $option_replacements);

unset ($option_matches);
unset ($option_replacements);

print_r ($options);
?>


Want the best answers? Ask the best questions!

TANSTAAFL!!
 
hi sleipnir214,
Thanks for the solution. I think array_combine is in 5 version. I am using 4.1.x so looking for some way around the array_combine functionality

Can you suggest something.
Thanks,
Dynamo
 
Replace the invocation of array_combine() with:

Code:
$options = array();
for ($counter = 0; $counter < count($option_matches); $counter++)
{
        $options[$option_matches[$counter]] = $option_replacements[$counter];
}


Want the best answers? Ask the best questions!

TANSTAAFL!!
 
Yep figured that out, but not getting the desired results.
the following results are returned

Code:
Array ( [Option1 ] => /var/abc; [Option2 ] => {Option1}/bcd; [Option3 ] => {Option1}/efg
Option1 is not replaced by its value i.e. /var/abc
whereas the result I want is the one you have mentioned earlier
Code:
Array
(
    [Option1] => /var/abc
    [Option2] => /var/abc/bcd
    [Option3] => /var/abc/efg
    [Option4] => /var/abc/efg/hij
)
 
I don't know what to tell you.

Here is my test configuration file:

Code:
Option1:/var/abc
Option2:{Option1}/bcd
Option3:{Option1}/efg
Option4:{Option3}/hij

here is my script:

Code:
<?php
function cleanup (&$item, $key)
{
        $item = str_replace('{', '', $item);
        $item = str_replace('}', '', $item);
}

$fh = fopen ('test_option.txt', 'r') or die('Could not open config file');

$option_matches = array();
$option_replacements = array();
while ($line = fgets($fh))
{
        $line = rtrim($line);
        $option_array = explode (':', $line);

        if (strstr($option_array[1], '{'))
        {
                $option_array[1] = str_replace($option_matches,
$option_replacements, $option_array[1]);

        }

        $option_matches[] = '{' . $option_array[0] . '}';
        $option_replacements[] = $option_array[1];
}

array_walk ($option_matches, 'cleanup');
//$options = array_combine ($option_matches, $option_replacements);

$options = array();
for ($counter = 0; $counter < count($option_matches); $counter++)
{
        $options[$option_matches[$counter]] = $option_replacements[$counter];
}

unset ($option_matches);
unset ($option_replacements);

print_r ($options);


?>

And here is my output:

Code:
Array
(
    [Option1] => /var/abc
    [Option2] => /var/abc/bcd
    [Option3] => /var/abc/efg
    [Option4] => /var/abc/efg/hij
)




Want the best answers? Ask the best questions!

TANSTAAFL!!
 
Thanks a lot sleipnir214, it worked. I must be doing something wrong earlier.
Again thanks a lot for helping me out.
Dynamo.
 
Just keep one think in mind....

When you are using a reference to another setting's value within a setting definition (as in the second line of the example config file), the setting referenced must have already been defined.

In other words, this will work:

Option1:/var/abc
Option2:{Option1}/bcd

This will not

Option2:{Option1}/bcd
Option1:/var/abc

because in the first line, Option1 has not yet been defined.

You probably already realized this, but I wanted to explicitly state it.


Want the best answers? Ask the best questions!

TANSTAAFL!!
 
hi sleipnir214,
Run into one more problem
how do we parse this case
Code:
hostDomain: abc.com
BASEPATHSECURE : [URL unfurl="true"]http://users.{hostDomain}/[/URL]

Thanks,
Mohit
 
You mean to deal with spurious whitespace and the presence of colons in the option values?

Change this:

$option_array = explode (':', $line);

To read:

$option_array = explode (':', $line[red],2[/red]);

[red] $option_array[0] = trim($option_array[0]);
$option_array[1] = trim($option_array[1]);[/red]


This will make the script assume that the first colon in a line is the separator between an option name and an option value. Any additional colons in a line are considered parts of values.


Want the best answers? Ask the best questions!

TANSTAAFL!!
 
Hi sleipnir214,
As in the parsing routine you had mentioned that the setting referenced must have already been defined. However now I have to make some more changes in the parsing routine.
As we have two server, one development and one production so for ease of portability I divided the file to be parsed into two different file, while one file contains the global variables and other file contains variables specific to a server (development or production).
the two files are
Code:
 a.conf which contains 
HostDomain : domain.tld
User : XYZ
the second file is b.conf which contains
Code:
BASEPATH = [URL unfurl="true"]http://users.{HostDomain}[/URL]
now I have to parse the two files and then somehow put the parsed valued from file a.conf into file b.conf i.e. the value of the HostDomain from a.conf into b.conf.
I am unable to find a way of doing this. Would appreciate any help.
Thanks,
Dynamo
 
Is the equals-sign in b.conf a typo or have you changed your own data specification?

Assume a.conf should read:
Code:
HostDomain : domain.tld
User : XYZ

And assume b.conf should have read:
Code:
BASEPATH [red]:[/red] [URL unfurl="true"]http://users.{HostDomain}[/URL]

And further assume c.conf contains:
Code:
USERPATH : [URL unfurl="true"]http://{User}.{HostDomain}[/URL]

Then it is a fairly simple matter of changing the code so that it loops through multiple files:
Code:
<?php
function cleanup (&$item, $key)
{
	$item = str_replace('{', '', $item);
	$item = str_replace('}', '', $item);
}

function read_options ($filenames)
{
	$options = array();
	$option_matches = array();
	$option_replacements = array();
	
	foreach ($filenames as $filename)
	{
		$fh = fopen ($filename, 'r') or die('Could not open config file');
		
		while ($line = fgets($fh))
		{
			$line = rtrim($line);
			$option_array = explode (':', $line, 2);
	
			$option_array[0] = trim($option_array[0]);
			$option_array[1] = trim($option_array[1]);		
	
			if (strstr($option_array[1], '{'))
			{
				$option_array[1] = str_replace($option_matches, $option_replacements, $option_array[1]);
			}
			
			$option_matches[] = '{' . $option_array[0] . '}';
			$option_replacements[] = $option_array[1];
		}
	}
		
	array_walk ($option_matches, 'cleanup');
	
	for ($counter = 0; $counter < count($option_matches); $counter++)
	{
		$options[$option_matches[$counter]] = $option_replacements[$counter];
	}
	
	return $options;
}

$filenames = array ('a.conf', 'b.conf', 'c.conf');

$options = read_options ($filenames);
print '<pre>';
print_r ($options);	
?>

returns:

Code:
Array
(
    [HostDomain] => domain.tld
    [User] => XYZ
    [BASEPATH] => [URL unfurl="true"]http://users.domain.tld[/URL]
    [USERPATH] => [URL unfurl="true"]http://XYZ.domain.tld[/URL]
)


Want the best answers? Ask the best questions!

TANSTAAFL!!
 
Hi,
Appreciate your quick response.
But I am getting these error msgs

Code:
Warning: Wrong parameter count for fgets() in /usr/local/abc/web/users.abc.com/parsing.php on line 18

Warning: Wrong parameter count for fgets() in /usr/local/abc/web/users.abc.com/parsing.php on line 18

Array
(
)

Line 18 is
Code:
foreach ($filenames as $filename)
    {
        [COLOR=red]$fh = fopen ($filename, 'r') or die('Could not open config file');[/color]
        
        while ($line = fgets($fh))

the error msg is because $filename is empty.
in place of $filename if $filenames is used it gives the following error msg
Code:
fopen("Array", "r") - No such file or directory
Yes "=" is a typo.
Thanks,
Dynamo
 
Hi,
Found out what the problem is with fgets you have to define the lenght which will be returned/read from the file pointed to by handle
like fgets($file, 1000)

Thanks,
Dynamo
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top