(Developer Shed Network) Server Side - PHP - Easy Application Configuration With PatConfiguration
(Developer Shed Network) Server Side - PHP - Easy Application Configuration With PatConfiguration
Table of Contents
Getting Real.........................................................................................................................................................1 Plug And Play......................................................................................................................................................2 Your Friendly Neighbourhood Spiderman......................................................................................................3 Anatomy Class.....................................................................................................................................................5 Version Control...................................................................................................................................................8 The Write Stuff.................................................................................................................................................10 Speaking Native .................................................................................................................................................14 Not Your Type...................................................................................................................................................16 When Time Is Money, Recycle!.......................................................................................................................19 Cache Cow.........................................................................................................................................................22 Link Zone ...........................................................................................................................................................23
Getting Real
The nice thing about the opensource community is that no matter how arcane your requirement, there's usually someone out there who's got a tool to help you meet it. It might not be the best tool in the world, it might be a little rough around the edges, it might not even look very pretty, but it'll usually get the job done. And you won't pay a cent for it. Take, for example, the task of manipulating application configuration data. You know what I mean asking the user for configuration values at install time, saving this data to a file, and using it when required at run time. It's a pretty simple exercise, and one that's fairly standard across every application and, like me, you've probably done it a few hundred times over the last couple years without even thinking about it. Unlike me, though, you probably had the good sense to create a library of reusable functions to help you accomplish this task quickly, and with minimal effort. If you did, you probably don't need to read any further; you can log off and catch some zzzzs instead, since you're obviously a Real Programmer, and everyone knows that Real Programmers need their beauty sleep... If, on the other hand, you still handcraft the code to manage your configuration data every time you build an application, you're definitely going to want to read this article it's your first step on the road to Real Programmerhood. Flip the page, and let me tell you all about patConfiguration.
Getting Real
<?xml version="1.0" encoding="UTF8"?> <configuration> <path name="mail"> <configValue name="fromname" type="string">Peter Parker</configValue> <configValue name="fromaddress" type="string">[email protected]</configValue> </path> </configuration>
The XML file above contains configuration data in a format that is understood by patConfiguration. As you can see, a patConfigurationcompliant configuration file must conform to the standard rules of XML markup, and must contain a <configuration> root element. Configuration values can be grouped together under this root element using <path> elements, with every variablevalue pair represented by a <configValue> element. Variablevalue pairs are accessed by drilling down the tree of <path> elements until the desired node is reached. For example, to access the value of the email address
mail.fromaddress.
patConfiguration allows you to nest <path> elements to any depth the following is a perfectly valid configuration file:
<?xml version="1.0" encoding="UTF8"?> <configuration> <path name="application"> <configValue name="name" type="string">SomeApp</configValue> <configValue name="version" type="string">2.3</configValue>
<path name="window"> <configValue name="height" type="int">600</configValue> <configValue name="width" type="int">500</configValue> <path name="list"> <configValue name="maxItems" type="int">5</configValue> </path> </path> </path> </configuration>
You can even link the values in a configuration file with each other via the <getConfigValue> element consider the following example, which uses the application name and version number to dynamically create a variable containing the window title:
<?xml version="1.0" encoding="UTF8"?> <configuration> <path name="application"> <configValue name="name" type="string">SomeApp</configValue> <configValue name="version" type="string">2.3</configValue> <path name="window"> <configValue name="height" type="int">600</configValue> <configValue name="width" type="int">500</configValue> <configValue name="title" type="string"> <getConfigValue path="application.name" /> <getConfigValue path="application.version" /> </configValue> </path> </path> </configuration>
The variablevalue pairs in this configuration file can be read and manipulated by patConfiguration in the context of a PHP application. Let's look at that next.
Anatomy Class
Next, it's time to use the patConfiguration engine to read and use the values in the configuration file. Here's how:
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // read config file $conf>parseConfigFile("config.xml"); // print configuration print_r($conf>getConfigValue()); ?>
Array ( [application.name] => SomeApp [application.version] => 2.3 [application.window.height] => 600 [application.window.width] => 500 [application.window.list.maxItems] => 5 )
Anatomy Class
1. The first step is, obviously, to include all the relevant files for the class to work.
Once that's done, I can safely create an object of the patConfiguration class.
This object instance will serve as the primary access point to the data in the application configuration file(s), allowing me to do all kinds of nifty things with it. 2. Next, the object's setConfigDir() method is used to set the default location of the configuration files,
and the parseConfigFile() method is used to actually read each file into the object's internal stack.
You can parse multiple configuration files by calling parseConfigFile() for each file, and telling Anatomy Class 6
patConfiguration to append (instead of overwriting) each set of configuration variables to the existing stack via the additional "a" option as in the following code snippet:
4. Finally, all that's left is to actually use the configuration data in this case, print it all to the standard output device.
The getConfigValue() method gets the value of a specified configuration variable from the configuration file(s). If no variable name is specified, the entire set of values is returned...as in the example above.
Anatomy Class
Version Control
Let's now consider a variant of the example on the previous page, this one printing the value of a single configuration variable:
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // read config file $conf>parseConfigFile("config.xml"); // get configuration values print_r($conf>getConfigValue("application.version")); ?>
In this case, since the getConfigValue() method receives the path and name of the configuration value to be retrieved, only that value is retrieved and printed. Here's a more realistic example, this one using an XML configuration file containing MySQL database access parameters
<?xml version="1.0" encoding="UTF8"?> <configuration> <path name="mysql"> <configValue name="host" type="string">localhost</configValue> <configValue name="user" type="string">joe</configValue> <configValue name="pass" type="string">secret</configValue> <configValue name="db" type="string">db456</configValue> </path> </configuration>
Version Control
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // read config file $conf>parseConfigFile("config.xml"); // get and use configuration values $connection = mysql_connect( $conf>getConfigValue("mysql.host"), $conf>getConfigValue("mysql.user"), $conf>getConfigValue("mysql.pass") ) or die ("Unable to connect!"); mysql_select_db( $conf>getConfigValue("mysql.db") ) or die ("Unable to select database!"); $query = "SELECT * FROM users"; $result = mysql_query($query) or die ("Error in query: $query. " . mysql_error()); mysql_close($connection); ?>
Version Control
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set config values $conf>setConfigValue("screen.width", 500); $conf>setConfigValue("screen.height", 650); // write file $conf>writeConfigFile("config.xml", "xml"); ?>
The setConfigValue() method accepts two primary parameters variable name and corresponding value and a third optional parameter, which is the datatype of the variable being set (if this third value is omitted, patConfiguration will automatically determine the variable type). Valid type values include "string", "integer", "boolean", "float" and "array" I'll be discussing these again a little further down. Once the variablevalue pairs have been created, the writeConfigFile() method is called to actually write the configuration data to a file. In addition to the file name, patConfiguration also allows you to specify the file format "xml" or "php" together with a couple of miscellaneous options that adjust the behaviour of the writeConfigFile() method. Here's the output of the example above:
10
<?xml version="1.0" encoding="ISO88591"?> <configuration> <path name="screen"><configValue name="height" type="int">650</configValue><configValue name="width" type="int">500</configValue> </path></configuration>
Having trouble reading it? Have patConfiguration indent it a little more neatly with the additional "mode" parameter:
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set config values $conf>setConfigValue("screen.width", 500); $conf>setConfigValue("screen.height", 650); // write file $conf>writeConfigFile("config.xml", "xml", array("mode" => "pretty")); ?>
11
You can set multiple configuration values at a time via the setConfigValues() method, which accepts an array of variablevalue pairs
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // create array of configuration values $config = array( "screen.height" => 650, "screen.width" => 500 ); // add to configuration table $conf>setConfigValues($config); // write file $conf>writeConfigFile("a.xml", "xml"); ?>
12
require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set and display value $conf>setConfigValue("name", "Superman"); echo $conf>getConfigValue("name"); // clear and check to see if value exists $conf>clearConfigValue("name"); echo $conf>getConfigValue("name"); ?>
Note that if no path is provided to clearConfigValue(), the entire configuration table is cleared.
13
Speaking Native
If XML isn't really your cup of tea, patConfiguration can also create configuration files using traditional PHP as well this can work better in some cases, since the configuration file only needs to be include()d in your application, not parsed by an XML parser as well. Consider the following example and its output, which demonstrate how this works:
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set config values $conf>setConfigValue("screen.width", 500); $conf>setConfigValue("screen.height", 650); // write file $conf>writeConfigFile("config.php", "php"); ?>
<?PHP // Configuration generated by patConfiguration $config = array(); $config["screen.height"] = 650; $config["screen.width"] = 500; ?>
Speaking Native
14
As you can see, the variable value pairs defined in the patConfiguration table get converted into a PHP associative array and written to a file. By default, this associative array is named $config you can change it by providing an alternative name via the "varname" argument to writeConfigFile().
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set config values $conf>setConfigValue("screen.width", 500); $conf>setConfigValue("screen.height", 650); // write file $conf>writeConfigFile("config.php", "php", array("varname" => "appConfig")); ?>
<?PHP // Configuration generated by patConfiguration $appConfig = array(); $appConfig["screen.height"] = 650; $appConfig["screen.width"] = 500; ?>
Speaking Native
15
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set config values $conf>setConfigValue("screen.width", 500, "integer"); $conf>setConfigValue("font.face", "Verdana", "string"); $conf>setConfigValue("window.toolbar.visibility", true, "boolean"); // write file $conf>writeConfigFile("config.xml", "xml", array("mode" => "pretty")); ?>
<?xml version="1.0" encoding="ISO88591"?> <configuration> <path name="font"> <configValue name="face" type="string">Verdana</configValue> </path>
16
<path name="screen"> <configValue name="width" type="int">500</configValue> </path> <path name="window"> <path name="toolbar"> <configValue name="visibility" type="bool">true</configValue> </path> </path> </configuration>
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set config values $conf>setConfigValue("friends", array("Rachel", "Ross", "Monica", "Joey", "Chandler", "Phoebe"), "array"); // write file $conf>writeConfigFile("config.xml", "xml", array("mode" => "pretty")); ?>
17
<?xml version="1.0" encoding="ISO88591"?> <configuration> <configValue name="friends" type="array"> <configValue type="string">Rachel</configValue> <configValue type="string">Ross</configValue> <configValue type="string">Monica</configValue> <configValue type="string">Joey</configValue> <configValue type="string">Chandler</configValue> <configValue type="string">Phoebe</configValue> </configValue> </configuration>
<?PHP // Configuration generated by patConfiguration $config = array(); $config["friends"] = array(); $config["friends"][0] = "Rachel"; $config["friends"][1] = "Ross"; $config["friends"][2] = "Monica"; $config["friends"][3] = "Joey"; $config["friends"][4] = "Chandler"; $config["friends"][5] = "Phoebe"; ?>
18
<patTemplate:tmpl name="form"> <html> <head><basefont face="Arial"></head> <body> <h2>Configuration</h2> <table border="0" cellspacing="5" cellpadding="5"> <form action="configure.php" method="post"> <tr> <td>MySQL host name</td> <td><input type="text" name="db_host" value="{DB_HOST}"></td> </tr> <tr> <td>MySQL user name</td> <td><input type="text" name="db_user" value="{DB_USER}"></td> </tr> <tr> <td>MySQL user password</td> <td><input type="text" name="db_pass" value="{DB_PASS}"></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" name="submit" value="Save Configuration"></td> </tr> </form> </table> </body> </html> </patTemplate:tmpl>
19
<? // include classes require("patConfiguration.php"); require("patTemplate.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // create patTemplate object $template = new patTemplate; // set template location $template>setBasedir("templates"); // add templates to the template engine $template>readTemplatesFromFile("configuration.tmpl"); // form not yet submitted if (!$_POST["submit"]) { // check to see if config file exists if (file_exists("config/config.xml")) { // parse it and display configuration values $conf>parseConfigFile("config.xml"); $template>AddVar("form", "DB_HOST", $conf>getConfigValue("db.host")); $template>AddVar("form", "DB_USER", $conf>getConfigValue("db.user")); $template>AddVar("form", "DB_PASS", $conf>getConfigValue("db.pass")); } // parse and display the template $template>displayParsedTemplate("form"); } else { // accept the submitted values // and write them to a configuration file $conf>setConfigValue("db.host", $_POST['db_host']);
20
$conf>setConfigValue("db.user", $_POST['db_user']); $conf>setConfigValue("db.pass", $_POST['db_pass']); $conf>writeConfigFile("config.xml", "xml", array("mode" => "pretty")); } ?>
In this case, patConfiguration is used to read the application's database configuration from a file via the parseConfigFile() method and display the variablevalue pairs contained within that file in an editable HTML form. The user may then modify these values and submit the form; patConfiguration will accept the new values and write them back to the configuration file via writeConfigFile(). This kind of application configuration is pretty common to most Webbased tools and patConfiguration lets you build an interface around it quickly and efficiently, with maximum code reuse and minimal time wastage.
21
Cache Cow
Normally, patConfiguration parses your XML configuration file every time you need to load configuration data; this is expensive, in terms of both time and processor cycles. In these situations, you can obtain a performance improvement by using patConfiguration's builtin cache, which uses a serialized representation of the XML data to speed up load time. Using a cache is pretty easy consider the following example, which demonstrates how:
<? // include class require("patConfiguration.php"); // create patConfiguration object $conf = new patConfiguration; // set config file locations $conf>setConfigDir("config"); // set cache locations $conf>setCacheDir("cache"); // read config file $conf>loadCachedConfig("config.xml"); // get configuration values print_r($conf>getConfigValue("application.version")); ?>
Using the cache is thus simply a matter of setting a cache directory and using the loadCachedConfig() method instead of the parseConfigFile() method. If the file does not already exist in the cache, patConfiguration will locate it, read and serialize it, and use the serialized version in all subsequent calls. When the data in the original file changes, this change is detected by patConfiguration and the cache is updated with the new data. Finally, patConfiguration also comes with a number of extensions to simplify integration with, and configuration of, other pat classes extensions are currently available for the patTemplate, patUser and patDbc classes, and the source distribution comes with numerous examples of how they may be used. I'm not going to get into the details here, but you should certainly take a look at this once you're comfortable with the basics of using patConfiguration.
Cache Cow
22
Link Zone
That's about it for the moment. In this article, I introduced you to the patConfiguration class, which is designed primarily to assist you in the reading, writing and manipulation of configuration data. I showed you how to read and write configuration files in both XML and PHP format, and how to use patConfiguration's builtin methods simplify and speed up configuration tool development, and improve performance by caching frequentlyaccessed configuration data. If you'd like to learn more about patConfiguration and its related tools, you should take a look at the following links: The official patConfiguration Web site, at http://www.phptools.de/ Webbased application development with patTemplate, at http://www.devshed.com/Server_Side/PHP/patTemplate/ patConfiguration API documentation, at http://www.phptools.de/site.php?&file=patConfigurationDocApi.xml Extending patConfiguration, at http://www.phptools.de/site.php?&file=patConfigurationDocExtensions.xml Till next time...ciao! Note: All examples in this article have been tested on Linux/i586 with PHP 4.2.3, Apache 1.3.23 and patConfig 1.3. Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!
Link Zone
23