mirror of
https://github.com/php/php-src.git
synced 2024-10-06 09:16:11 +00:00
429 lines
14 KiB
Plaintext
429 lines
14 KiB
Plaintext
Documentation and Tutorial for PEAR-Config
|
|
|
|
by Alexander Merz
|
|
$Id$
|
|
|
|
A first example
|
|
|
|
For beginning we start with a useful script example:
|
|
|
|
----- example.php ------
|
|
|
|
<?php
|
|
|
|
require_once( "config.php" ) ;
|
|
|
|
$path = "c:/windows/system/" ; // change this to the location of $file
|
|
$file = "php.ini" ; // filename to parse
|
|
$options["cc"] = ';' ; // set the comment char
|
|
$blocks = array() ; // contains all blocknames
|
|
$data = $array() ; // contains all key-value-pairs
|
|
|
|
$conf = new Config( "IniFile") ; // Data container is a ini file
|
|
|
|
$conf -> parseInput( $path.$file, $options) ;
|
|
$blocks = $conf -> getBlocks( "/" ) ;
|
|
|
|
foreach( $blocks as $block ) { // read the k-v-p of every block
|
|
$data[$block] = $conf -> getValues( "/".$block ) ;
|
|
}
|
|
|
|
// output
|
|
?>
|
|
<html>
|
|
<head>
|
|
<title>Test for PEAR - Config</title>
|
|
</head>
|
|
<body>
|
|
<table>
|
|
<?php
|
|
foreach( $data as $d) {
|
|
echo "<tr><td colspan=\"2\">Block: $d</td></tr>" ;
|
|
foreach( $d as $k => $v ) {
|
|
echo "<tr><td>$k</td><td>$v</td></tr>" ;
|
|
}
|
|
}
|
|
?>
|
|
</table>
|
|
</body>
|
|
|
|
----- example.php ------
|
|
|
|
This script parses the php.ini and creates a table containing the name of all blocks and
|
|
the key-value-pairs of every block.
|
|
|
|
Now, lets cut up the script.
|
|
|
|
require_once( "config.php" ) ;
|
|
|
|
First of all, to use the Config-API you have to include
|
|
"config.php". If you have a regular PHP installation including PEAR, there should be
|
|
no problem for PHP to find the file. Unfortunatly a large number of ISP didn't installed PEAR
|
|
or have a older installation, where Config isn't present. In this case, we have good news for
|
|
you.
|
|
|
|
Config is "pure" PHP. This means you can download "config.php" and (important!) the
|
|
Config directory from cvs.php.net and copy the files to your webspace. Take care of using the
|
|
correct path to "config.php" in the require statement. Also, go this way, if you perhaps want
|
|
to use a newer version of Config.
|
|
|
|
$conf = new Config( "IniFile") ;
|
|
|
|
With this line you create a new instance of the Config class. The constructor requires the
|
|
declaration of the type of the container, which contains the configuration data. Check the
|
|
'Implementations' section in this documentation the see which containers are avaible at the
|
|
moment.
|
|
|
|
"php.ini" is a typical example for a ini file and should be present on your system, if you have
|
|
installed PHP ( else this document should be a bit useless for you!?). So, to work with this
|
|
file, we have to say Config to parse this file.
|
|
|
|
$conf -> parseInput( $path.$file, $options) ;
|
|
|
|
Normaly this function reads the data container and writes the data into an internal data
|
|
structure. How to adress specific the container depends on the implemention, IniFile
|
|
requires an existing file. The second parameter contains a set of options. Which options exist
|
|
and/ or required depends on the type of the container. In this case, Ini files have often
|
|
comments, which should not be parsed, "php.ini" uses the semicolon to mark up the start of
|
|
a comment.
|
|
|
|
At this point, we can start to accessing the configuration data.
|
|
|
|
To accessing the data, you should know something about how Config 'structurize' the data.
|
|
Config distinguish three types of elements: keys, values and blocks. Take a look on "php.ini".
|
|
|
|
The first 'key' is "engine". Keys are names of options and/or of data elements. To every key
|
|
belongs a 'value'. The value of the key "engine" could be "on" or "off". "on" or "off" are
|
|
data of the key. Take care, also missing of such data, ie. a empty string is a value.
|
|
|
|
Often, ie. "php.ini", the data container contains a huge number of key-value pairs. Sometimes
|
|
it isn't possible to avoid two or more options with the same key name, ie. you want to save
|
|
the access data for databases with different usernames, passwords and tablenames. To separate
|
|
them, you can edge them in a 'block'. Another typical use of blocks is to summarize
|
|
key-values pairs which belong together in a block, as you can see in "php.ini". Especially, if
|
|
a data container should be editable be humans without a special programm, you should use blocks
|
|
to structurize the data.
|
|
|
|
The data in "php.ini" is completly separate into blocks, so as the first access, we want the
|
|
names of the blocks.
|
|
|
|
$blocks = $conf -> getBlocks( "/" ) ;
|
|
|
|
getBlocks() returns an array containing all block names. You maybe wonder about the argument.
|
|
getBlocks requires a 'blockpath'. Config structurize the data as a tree comparable to a
|
|
file system. Think blocks as directories and key-value pairs as files. You can store a file
|
|
in the root dir ( "/" under Unix-like systems) or in a directory ( ie. ( "/usr/" ) or
|
|
subdirectories ( ie. "/usr/bin/" ). According to this, there are implementations which
|
|
support sub-blocks in blocks.
|
|
|
|
IniFile doesn't support block nesting, only blocks in the first level, the 'root' level and
|
|
the root level is adressed with a single slash.
|
|
|
|
Take care: If you want all sub blocks of ie. the block named "db_accessdata", the blockpath is
|
|
"/db_accessdata/" - don't forget the leading root slash! Also, if you need to address
|
|
key-value-pairs, as you can see later in this manual, which are not in a block, you have to
|
|
use "/" as blockpath.
|
|
|
|
As the next we want all key-value pairs of every block. To get them we use
|
|
|
|
$data[$block] = $conf -> getValues( "/".$block ) ;
|
|
|
|
to recieve them. getValues() returns a hash with all key-value pairs in the given block path.
|
|
The key will used as hash key containing the value of the key,
|
|
ie: $data[ 'PHP' ][ 'engine' ] = "on".
|
|
|
|
So thats all, what would be worthy to talk about the script! Now a little exercise for you:
|
|
You should able to rewrite the script to print out the content of every configuration data
|
|
container including key-value-pairs in subblocks.
|
|
|
|
Getting and Setting
|
|
|
|
getValues is a possibility to get all config data of a block. But often you need only
|
|
a few of them and/ or you want more influence oft the returned data.
|
|
|
|
To only get the value of one key, you can use getValue(). getValue() requires the blockpath as
|
|
the first argument like dicussed above, as the next the name of the key as a string.
|
|
getValue() has a third optional parameter. If the key in the named block doesn't exists, the
|
|
key and if neccessary the block will be created and the third parameter will be assigned
|
|
to them and returned by getValue().
|
|
|
|
The counterpart of getValue() is setValue(). setValue() requires a blockpath, the name of the
|
|
key too, but as the third argument the value, which should be assigned to the key. The behavior
|
|
of setValue, if the key or the block not exists, is the same like getValue(). setValue()
|
|
returns the assigned value too.
|
|
|
|
Saving changes
|
|
|
|
If you changed values of keys or adding keys or blocks, this changes only influence the
|
|
internal data structure of Config. So changes will lost during finishing the script.
|
|
To save them permantly, you have to call writeInput(). writeInput has two optional
|
|
arguments. The first is the name of the data container, where the data should be saved.
|
|
If you left this part empty, writeInput() use the data container given in parseInput() as
|
|
destination.
|
|
|
|
The second optional argument orders writeInput() to save the data preserving the
|
|
content and format of the original container, as good as possible, if the argument is true.
|
|
This option makes in the most cases only sense in file-based containers like IniFile. Normaly
|
|
configuration files contains ie. comments, a lot of whitespaces to make the files editable by
|
|
humans. This data will not be parsed into the internal data struture and so cannot be written
|
|
back to the container. If the preserving argument is true, writeInput() takes the original
|
|
container and tries to copy the content, and changes only different values and adds new keys and
|
|
blocks keeping the original file content including comments and whitespace.
|
|
|
|
Implementations
|
|
|
|
IniFile
|
|
|
|
The container is a file with following format
|
|
|
|
...
|
|
; comment
|
|
[blockname] ; comment
|
|
key=value ; comment
|
|
key="value with whitespaces; and the comment char" ; comment
|
|
...
|
|
|
|
Comments are marked by a special starting comment char and can stay on a single line
|
|
or after a value, but not between a key-value assignment.
|
|
|
|
Blocks are marked between brackets and the block name between them. There is no block end
|
|
markup. A block ist finish by the end of the file or a new block markup. Block nesting is not
|
|
possible.
|
|
|
|
Only one key-value assignment per line is allowed. The assignment consist of the keyname, a
|
|
equal sign and the value. If the value contains whitespace or the comment char, you have to
|
|
set the value between double marks.
|
|
|
|
Options for parseInput() are:
|
|
"cc" - defines the comment char
|
|
|
|
|
|
XML (by Christian Stocker <chregu@phant.ch>)
|
|
|
|
The main advantage of the XML-Container is, that it knows Sub-blocks. So you can
|
|
have nested blocks, which I have to use from time to time.
|
|
The XML-Container depends on the domxml implementation of PHP, therefore you
|
|
have to compile you're PHP with the option --with-domxml (or ask you're provider
|
|
to do so...)
|
|
|
|
An example XML-file looks this way
|
|
|
|
<?xml version="1.0"?>
|
|
<block1 key1="value1">
|
|
<block2 key2="value2" key3="value3"/>
|
|
</block1>
|
|
|
|
The XML-File has to be well-formed, otherwise you get an error.
|
|
|
|
The Constructor has to be called the following way
|
|
|
|
$conf = new Config( "xml") ;
|
|
|
|
accessing these values works the same as in the IniFile-Container, except for
|
|
Sub-blocks you can use the Directory-structure mentioned above. For example, if
|
|
you want the values of Block2:
|
|
|
|
$conf->getValues("/block1/block2/");
|
|
|
|
Options (default value in brackets):
|
|
|
|
IncludeContent [True] Since an xml-tags also can have content (not only
|
|
attributes), this flag indicates if we want to take
|
|
this as a value for the block.
|
|
example:
|
|
...
|
|
<block1>This is content</block1>
|
|
...
|
|
$data = $conf->getValues("/block1/");
|
|
would give us
|
|
$data[content] = "This is content";
|
|
|
|
Be aware:
|
|
<block1>This is content<block2> and this also</block2></block1>
|
|
...
|
|
$data = $conf->getValues("/block1/");
|
|
gives you
|
|
$data[content] = "This is content and this also";
|
|
|
|
IncludeChildren [True] For more flexibility in parsing your config files,
|
|
there's an array containin all the names of the sub-
|
|
blocks of one block, if you set this.
|
|
...
|
|
<block1 key1="value1">
|
|
<block2 key2="value2" key3="value3"/>
|
|
<block3 key4="value2" key5="value3"/>
|
|
</block1>
|
|
...
|
|
$data = $conf->getValues("/block1/");
|
|
gives you an array with the values:
|
|
[key1] => value1
|
|
[children] => Array
|
|
(
|
|
[0] => block2
|
|
[1] => block3
|
|
)
|
|
you can then get the values of block2 and block3
|
|
with a simple foreach-loop:
|
|
|
|
foreach ($data[children] as $childname) {
|
|
$childdata = $conf->getValues("/block1/".$childname);
|
|
}
|
|
|
|
MasterAttribute [Null] You can assign one attribute of a block as a
|
|
MasterAttribute, then the value of this attribute
|
|
will be assigned to the parent-block with the name
|
|
of the sub-block (which have the MasterAttribute) as
|
|
the key and the value of the MasterAttribute. You
|
|
can also set "content" as the MasterAttribute.
|
|
|
|
Example:
|
|
MasterAttribute = "key2";
|
|
$data = $conf->getValues("/block1/");
|
|
gives you an array with the values:
|
|
[key1] => value1
|
|
[block2] => value2
|
|
|
|
|
|
IncludeMasterAttribute [True] If you want to include the MasterAttribute also
|
|
i n the subblocks, set this flag.
|
|
MasterAttribute = "key2";
|
|
$data = $conf->getValues("/block1/block2");
|
|
gives you an array with the values:
|
|
[key2] => value2
|
|
[key3] => value3
|
|
|
|
if you set the flag False, then [key2] will not be included.
|
|
|
|
Limitations:
|
|
|
|
There can't be 2 Blocks on the same level with the same name. The following will
|
|
not reasonably work:
|
|
|
|
<block2 key2="value2" key3="value3"/>
|
|
<block2 key2="value3" key4="value4"/>
|
|
|
|
Writing is not supported yet. you can't write back the changes you made. Since
|
|
xml files can be written in different ways meaning almost the same, it's hard to
|
|
preserve the old format. But it's certainly possible..
|
|
|
|
DB
|
|
|
|
you can store you're config data also in a Database. This implementation uses
|
|
the Pear::DB Classes, so any Database supported within pear should be supported
|
|
here also.
|
|
|
|
the table in the Database has to look the following way (the length of the
|
|
varchar does not matter and additional fields can be included.)
|
|
|
|
CREATE TABLE config (
|
|
datasrc varchar(50) NOT NULL,
|
|
block varchar(50) NOT NULL,
|
|
name varchar(50) NOT NULL,
|
|
value varchar(50) NOT NULL
|
|
);
|
|
|
|
Calling the constructor:
|
|
|
|
$conf = new Config("db","mysql://username:password@localhost/dbname") ;
|
|
|
|
the second parameter is the dsn, as described in the pear-db documentation.
|
|
|
|
The rest is quite the same as in the IniFile-Implementation. Just try to replace
|
|
the constructor-line in the examples for the IniFile-Container and the rest
|
|
should work.
|
|
|
|
datasrc: it's the equivalent to the filename. so you can have different "ini-files" in the same db-table (for example to store different settings for different users)
|
|
|
|
block/name/value: has the same meaning as in the IniFile-Container.
|
|
|
|
|
|
|
|
Writing back the data is also supported.
|
|
Sub-blocks are not supported.
|
|
|
|
Options:
|
|
|
|
Table [config] The name of the db-table, where the keys/values/etc are
|
|
stored.
|
|
|
|
|
|
API-Reference
|
|
|
|
Config($storage_driver,$storage_options = "")
|
|
|
|
Constructor
|
|
|
|
Parameters
|
|
storage_driver - name of the data container
|
|
storage_options - n/a
|
|
|
|
array getBlocks( $block = "/")
|
|
|
|
returns all blocknames of the given blockpath
|
|
|
|
Parameters
|
|
block - existing blockpath
|
|
|
|
Return
|
|
array - array containing all blocknames
|
|
|
|
|
|
mixed getValue( $block = "/", $key, $default = "")
|
|
|
|
returns the value of the key in the block
|
|
|
|
Parameters
|
|
block - blockpath
|
|
key - key name
|
|
value - default value, if key not found
|
|
|
|
Return
|
|
mixed - the value of the key or the default value
|
|
|
|
|
|
array getValues( $block = "/")
|
|
|
|
returns all key-value-pairs of the given blockpath
|
|
|
|
Parameters
|
|
block - existing blockpath
|
|
|
|
Return
|
|
array - hash containing the key-value-pairs
|
|
|
|
mixed setValue( $block = "/", $key, $value = "")
|
|
|
|
sets the key in the block to the given value
|
|
|
|
Parameters
|
|
block - blockpath
|
|
key - key name
|
|
value - value to assign
|
|
|
|
Return
|
|
mixed - the given value
|
|
|
|
mixed parseInput ($src ,$options = array() )
|
|
|
|
set the data source to parse
|
|
|
|
Parameters
|
|
src - Source to parse
|
|
ooptions - array of the settings
|
|
|
|
Return
|
|
mixed - true on success, else PEAR_ERROR
|
|
|
|
mixed writeInput( $dest = "", $preserve = True )
|
|
|
|
writes the data to dest
|
|
|
|
Parameters
|
|
dest - Destination for writing
|
|
preserve - if true, try to preserve writing
|
|
|
|
Return
|
|
mixed - true if success, else PEAR_ERROR
|
|
|
|
|