<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>» DoYourself.org &#187; PHP</title>
	<atom:link href="http://www.doyourself.org/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.doyourself.org</link>
	<description>Did you know ?</description>
	<lastBuildDate>Fri, 30 Jul 2010 23:48:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Process XML configuration files with PHP</title>
		<link>http://www.doyourself.org/php/792-process-xml-configuration-files-with-php/</link>
		<comments>http://www.doyourself.org/php/792-process-xml-configuration-files-with-php/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 23:48:32 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=792</guid>
		<description><![CDATA[Summary: XML provides a convenient, easy-to-use expression language for an application&#8217;s configuration files. To extract this information into a PHP script can sometimes pose a challenge. That&#8217;s where the XJConf for PHP package comes in: It provides an API to read XML-encoded information and directly use it to configure PHP data structures like scalars, arrays [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><strong>Summary:</strong> XML provides a convenient, easy-to-use expression  language for an       application&#8217;s configuration files. To extract this information  into a PHP script can       sometimes pose a challenge. That&#8217;s where the XJConf for PHP  package comes in: It provides an API to read XML-encoded information and  directly use it to configure PHP data structures like scalars, arrays  and PHP objects. This article introduces the package and demonstrates  some useful real-world applications of its usage, including configuring  complex class trees and building a Web-based configuration interface.</p>
<p><a name="N10057">Introduction</a></p>
<p>As a general rule, when you develop any  reasonably-complex piece of software,           it&#8217;s a good idea to take time to identify the product&#8217;s key  configuration           variables, and then separate these from the standard variable  namespace and           place them in a separate area. With this process, you can  create a centralized           repository of application configuration information and   simplify the task of           modifying the product to work in different environment. It can  also help increase a developer&#8217;s familiarity with, and understanding  of, the key pieces of information needed to get the product up and  running.</p>
<p>Traditionally, configuration variables are stored in one (or more)           configuration files. The variables are often expressed using XML, which provides           a flexible framework for document authors to describe content using custom tags           and markup. In most cases, developers also need to construct a user interface to           interact with these XML configuration files, to read and use the configuration data contained therein.</p>
<p>XJConf for PHP helps PHP developers with this task. This  open-source package           provides an API to extract XML-encoded information from a  configuration file and           turn it into a native data structure, for immediate use within  an application. As such, it provides a robust, easy-to-use widget for  any PHP application.</p>
<p><a name="N10066">Install required software</a></p>
<p>The XJConf package is maintained by Frank Kleine and  Stephan Schmidt, and released to the PHP community under the GNU LGPL.  It requires PHP 5.0 (or better), and the easiest way to install it is  with the automated PEAR installer, which should have been included by  default with your PHP build. To install it, simply issue the following  commands at your shell prompt:</p>
<p><code>shell&gt; <strong>pear channel-discover pear.php-tools.net</strong> </code></p>
<p><code>shell&gt; <strong>pear install pat/XJConfForPHP-alpha</strong> </code></p>
<p>The PEAR installer will now connect to the new channel,  download the package, and install it to the appropriate location on your  system. This article uses XJConf for PHP V. 0.2.0.</p>
<p>To install the package manually, visit its home page, download the source code           archive, and manually uncompress the files to the desired location. You&#8217;ll find           links to the package home page, as well as to in-development builds, in the Resources of this article. Note that this manual installation process presupposes  some knowledge of PEAR&#8217;s package organization structure.</p>
<p>One final dependency: the XJConf for PHP package requires that you enable the           <code>xmlreader</code> extension of PHP. This extension is enabled           by default in PHP 5.1.0 or later. Users of older PHP versions can obtain           detailed information and activation instructions from the appropriate section of           the PHP manual (see Resources for links).</p>
<p>This article assumes that you have a working knowledge of  PHP and XML, and are comfortable using PHP&#8217;s simple and complex data  types. It assumes a reasonable degree of knowledge of both general OOP  concepts and the specific class model used by PHP 5, as well as some  knowledge of XML tree generation with PHP&#8217;s Document Object Model (DOM)  extension.</p>
<p><a name="N1009B">Understand basic usage</a></p>
<p>XJConf provides PHP application developers with an API that reads XML-formatted           configuration files and converts the data within them to native PHP data types           or custom objects. These data types or objects can then be used within a PHP           script in the normal fashion. Any XJConf-based program has three components:</p>
<ul>
<li>The XML-formatted configuration file</li>
<li>A PHP script that parses and extracts data from the configuration file</li>
<li>A definition file, which maps elements from the configuration file into native PHP structures</li>
</ul>
<p>The best way to illustrate the interaction of these three components is with an example. Consider Listing 1, which shows an XML configuration file for a pet housecat:<br />
<a name="c1"><strong>Listing 1. An XML configuration file (cat.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;cat&gt;
    &lt;name&gt;Martha&lt;/name&gt;
    &lt;age&gt;4&lt;/age&gt;
    &lt;breed&gt;Siamese&lt;/breed&gt;
&lt;/cat&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Now, suppose you need to read these configuration values into your PHP           application. The first step is to create a definition file, which maps each element from Listing 1 to a native PHP data type. Listing 2 illustrates such a file:<br />
<a name="c2"><strong>Listing 2. An XJConf definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
	&lt;tag name="name" type="string"/&gt;
	&lt;tag name="breed" type="string"/&gt;
	&lt;tag name="age" type="integer"/&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Take a moment to study the structure of this definition file, because           understanding it will be critical for all subsequent examples in this article.           An outer <code>&lt;defines&gt;</code> element encloses a series of           <code>&lt;tag&gt;</code> elements, each of which represents an element from the XML configuration file. Each <code>&lt;tag&gt;</code> must have at least the <code>name</code> and <code>type</code> attributes. The <code>name</code> attribute specifies an element name from the configuration file, while the <code>type</code> attribute specifies the corresponding PHP data type. Common primitive types are <code>string</code>, <code>integer</code> and <code>boolean</code>; however, as you&#8217;ll see a little further along in this article, you can also map an element to an array or a custom class.</p>
<p>All that&#8217;s left now is a PHP script to initialize an instance of XJConf and use the definitions in Listing 2 to retrieve configuration data. Listing 3 illustrates the required PHP code:<br />
<a name="c3"><strong>Listing 3. A PHP script to read XML configuration data</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

// load facade
XJConfLoader::load('XJConfFacade');
$conf = new XJConfFacade();

// attach definitions to parser
$conf-&gt;addDefinition('defs.xml');

// parse XML
$conf-&gt;parse('cat.xml');

// access XML element values
echo $conf-&gt;getConfigValue('name') . " is " . $conf-&gt;getConfigValue('breed')
. " and " . $conf-&gt;getConfigValue('age') . " year(s) old.";
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 4 illustrates the output of this script:<br />
<a name="c4"><strong>Listing 4. The output generated by Listing 3</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
Martha is Siamese and 4 year(s) old.
</pre>
</td>
</tr>
</tbody>
</table>
<p>Look closely at Listing 3, and it&#8217;s easy to understand what           it does. The listing first reads in the required class definition files, and           then loads and initializes an XJConf facade object. In XJConf, this object provides a          common interface to the <code>DefinitionParser</code> method, which handles the definition file in Listing 2; and           the <code>XMLParser</code> method, which handles the XML-formatted configuration file in Listing 1.</p>
<p>First, the script calls the <code>addDefinition()</code> method           of the <code>XJConfFacade</code> object to read the various tag           definitions from Listing 2 and attach these definitions to the           object. Next, the <code>parse()</code> method of the object parses the configuration data file in Listing 1.  During this parsing process, the elements and data in the configuration  file are converted into key-value pairs, similar to that found in a PHP  associative array.</p>
<p>Once parsing is complete (the process will stop with an error message if your          XML file definition has an error), you can access the keys and values with          the <code>getConfigValue()</code> method of the <code>XJConfFacade</code> object, which accepts a key name as argument and returns the corresponding value. Thus, in Listing 4, a call to <code>getConfigValue('name')</code> returns the value of the <code>&lt;name&gt;</code> element from the configuration file <code>cat.xml</code> (Listing 1), which in this case happens to be <code>Martha</code>.</p>
<p>Now, try to edit the values in the configuration file (Listing 1) such that it looks like Listing 5:<br />
<a name="c5"><strong>Listing 5. A revised configuration file</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;cat&gt;
    &lt;name&gt;Tom&lt;/name&gt;
    &lt;age&gt;1&lt;/age&gt;
    &lt;breed&gt;Norwegian&lt;/breed&gt;
&lt;/cat&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>And now, when you re-run the PHP script in Listing 4, you&#8217;ll see the revised output shown in Listing 6:<br />
<a name="c6"><strong>Listing 6. The revised output of Listing 4</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
Tom is Norwegian and 1 year(s) old.
</pre>
</td>
</tr>
</tbody>
</table>
<p>Notice that you didn&#8217;t have to change a single line of Listing 4 to access the revised configuration data. Thus, the benefits of  storing configuration variables in a separate file and using a tool like  XJConf to access them should be clear: Global changes become as simple  as altering a single file, with the changes reflecting instantly across  the application.</p>
<p><a name="N101A9">Configure arrays</a></p>
<p>Simple data types are just the tip of the iceberg—XJConf also lets you           define collections of related configuration variables, and converts these into           native PHP arrays. XJConf supports both numerically-indexed and associative arrays.</p>
<p>To see how this works, consider Listing 7, which sets up a configuration file containing a collection of values:<br />
<a name="c7"><strong>Listing 7. A data file containing a collection of related items (collection.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;root&gt;
    &lt;collection&gt;
        &lt;item letter="a"&gt;apples&lt;/item&gt;
        &lt;item letter="p"&gt;pears&lt;/item&gt;
        &lt;item letter="o"&gt;oranges&lt;/item&gt;
    &lt;/collection&gt;
&lt;/root&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 8 contains the corresponding definition file:<br />
<a name="c8"><strong>Listing 8. A definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="collection" type="array" /&gt;
    &lt;tag name="item" type="string" keyAttribute="letter" /&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Notice the values of the <code>type</code> attribute in this           definition file: The <code>&lt;collection&gt;</code> element is           mapped to an array, while the nested <code>&lt;item&gt;</code>s           are mapped to simple string values. Notice also a new attribute introduced in           this listing: The <code>keyAttribute</code> attribute, which tells           XJConf which element attribute to consider when it sets the keys of the output associative array.</p>
<p>Listing 9 has the PHP code that parses and displays the configuration data:<br />
<a name="c9"><strong>Listing 9. A PHP script to read XML configuration data into a PHP array</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

// load facade
XJConfLoader::load('XJConfFacade');
$xml = new XJConfFacade();

// attach definitions to parser
$xml-&gt;addDefinition('defs.xml');

// parse XML
$xml-&gt;parse('collection.xml');

// access XML element values
print_r($xml-&gt;getConfigValue('collection'));
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 10 displays the output:<br />
<a name="c10"><strong>Listing 10. The output of Listing 9</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
Array
(
    [a] =&gt; apples
    [p] =&gt; pears
    [o] =&gt; oranges
)
</pre>
</td>
</tr>
</tbody>
</table>
<p>By setting the <code>keyAttribute</code> to <code>letter</code>, XJConf automatically assigns the value of the <code>letter</code> attribute of every <code>&lt;item&gt;</code> element to the corresponding key of the output associative array.</p>
<p>Prefer a regular numerically-indexed array? Simply alter the definition file and set the value of the <code>keyAttribute</code> to the special symbol <code>__none</code>:<br />
<a name="c11"><strong>Listing 11. The revised definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="collection" type="array" /&gt;
    &lt;tag name="item" type="string" keyAttribute="__none" /&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>And Listing 12 now displays the revised output:<br />
<a name="c12"><strong>Listing 12. The revised output of Listing 9</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
Array
(
    [0] =&gt; apples
    [1] =&gt; pears
    [2] =&gt; oranges
)
</pre>
</td>
</tr>
</tbody>
</table>
<p>Now consider a realistic application of this feature:  Configuring a database connection from variables present in an XML  configuration file. Assume that the configuration file looks something  like Listing 13:<br />
<a name="c13"><strong>Listing 13. A XML database configuration file (conf.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;conf&gt;
    &lt;database&gt;
        &lt;user&gt;root&lt;/user&gt;
        &lt;pass&gt;mysql123&lt;/pass&gt;
        &lt;host&gt;localhost&lt;/host&gt;
        &lt;db&gt;test&lt;/db&gt;
    &lt;/database&gt;
&lt;/conf&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Further, assume that the task is to read these  configuration values into an array, and then use this array to connect  to a MySQL database server. The first step, then, is to map the XML into  an array using a definitions file like the one in Listing 14:<br />
<a name="c14"><strong>Listing 14. A definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="database" type="array"&gt;
        &lt;tag name="user" type="string" /&gt;
        &lt;tag name="pass" type="string" /&gt;
        &lt;tag name="host" type="string" /&gt;
        &lt;tag name="db" type="string" /&gt;
    &lt;/tag&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 15 has the PHP script that uses this data to attempt a MySQL database connection:<br />
<a name="c15"><strong>Listing 15. A PHP script to read and use database configuration data from an XML file</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

// load facade
XJConfLoader::load('XJConfFacade');
$xml = new XJConfFacade();

// attach definitions to parser
$xml-&gt;addDefinition('defs.xml');

// parse XML
$xml-&gt;parse('conf.xml');

// access database configuration array
$db = $xml-&gt;getConfigValue('database');

// test MySQL connection
$conn = mysql_connect($db['host'], $db['user'], $db['pass'])
or die('Connection error!');
mysql_select_db($db['db'], $conn) or die('Database selection error!');
mysql_close($conn);
echo 'Database test successful';
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 15 uses XJConf to create and populate an array named           <code>$db</code> with data from the configuration file  conf.xml. This array is then used to open a connection to the MySQL  database server and select a database for use. As explained in earlier  examples, the key to the script lies in the definition file, defs.xml,  which tells XJConf how to map elements from the configuration file into a  PHP array.</p>
<p><a name="N10282">Configure classes and objects</a></p>
<p>One of the most powerful features in XJConf, however,  lies in its support for           PHP classes and objects. With XJConf, it&#8217;s quite simple to  instantiate custom           objects from an XML configuration file, and even configure the   properties of said object using the data present in the configuration  file.</p>
<p>To illustrate this, let&#8217;s first define a simple <code>RectangularObject</code> class, which exposes three key properties to the configuration API: the length, width, and height. This class also exposes a <code>getVolume()</code> method, which uses these properties to calculate the volume of the object. Listing 16 has the code:<br />
<a name="c16"><strong>Listing 16. A PHP class definition (RectangularObject.php)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
class RectangularObject {

    // declare properties
    private $length;
    private $height;
    private $width;

    // declare constructor
    function __construct() {
        return true;
    }

    // declare setter methods
    function setLength($l) {
        $this-&gt;length = $l;
    }

    function setHeight($h) {
        $this-&gt;height = $h;
    }

    function setWidth($w) {
        $this-&gt;width = $w;
    }

    // declare other methods
    function getVolume() {
        return ($this-&gt;length * $this-&gt;width * $this-&gt;height);
    }
}
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 17 contains XML-formatted configuration data for one           such <code>RectangularObject</code> class:<br />
<a name="c17"><strong>Listing 17. An XML configuration file (data.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;conf&gt;
    &lt;rectangularobject&gt;
        &lt;height&gt;20&lt;/height&gt;
        &lt;width&gt;15&lt;/width&gt;
        &lt;length&gt;10&lt;/length&gt;
    &lt;/rectangularobject&gt;
&lt;/conf&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Mapping data into an object instance is fairly easy. All you need to do is set the <code>type</code> attribute to the name of the class you wish to instantiate. Listing 18 illustrates the corresponding definition:<br />
<a name="c18"><strong>Listing 18. An XJConf definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="rectangularobject" type="RectangularObject"&gt;
        &lt;tag name="length" type="integer"/&gt;
        &lt;tag name="width" type="integer"/&gt;
        &lt;tag name="height" type="integer"/&gt;
    &lt;/tag&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Assuming that the setter methods are correctly named, XJConf will do two           things</p>
<ol>
<li>Instantiate an object of that class.</li>
<li>Call setter methods for each nested element to automatically configure the        properties of the object.</li>
</ol>
<p>Thus, the <code>setLength()</code> method is automatically invoked for the <code>&lt;length&gt;</code> element, the <code>setHeight()</code> method for the <code>&lt;height&gt;</code> element, and so on.</p>
<p>Listings 19 and 20 illustrate the PHP code and output respectively:<br />
<a name="c19"><strong>Listing 19. A PHP script to instantiate and configure an object from XML data</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

// load class definition
include_once 'RectangularObject.php';

// load facade
XJConfLoader::load('XJConfFacade');
$xml = new XJConfFacade();

// attach definitions to parser
$xml-&gt;addDefinition('defs.xml');

// parse XML
$xml-&gt;parse('data.xml');

// access object instance
$instance = $xml-&gt;getConfigValue('rectangularobject');
print 'The volume of the object is: ' . $instance-&gt;getVolume() . ' units';
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 20 displays the output:<br />
<a name="c20"><strong>Listing 20. The output of Listing 19</strong></a></p>
<pre>
The volume of the object is: 3000 units

<a name="N10313">Configure default and mandatory Values</a>

You can write an XML configuration file using attributes  instead of nested tags, and use these attributes to configure an object  instance.  To see how this works in practice, first revise Listing 17 such that it uses attributes instead of nested elements:

<a name="c21"><strong>Listing 21. The revised XML configuration file (data.xml)</strong></a>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;conf&gt;
    &lt;rectangularobject height="20" width="15" length="10" /&gt;
&lt;/conf&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Obviously, this necessitates a change in the definition file as well:<br />
<a name="c22"><strong>Listing 22. The revised XJConf definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="rectangularobject" type="RectangularObject"&gt;
        &lt;attribute name="length" type="integer"/&gt;
        &lt;attribute name="width" type="integer"/&gt;
        &lt;attribute name="height" type="integer"/&gt;
    &lt;/tag&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>This change consists of replacing the <code>&lt;tag&gt;</code> elements with <code>&lt;attribute&gt;</code> elements, thus telling XJConf to consider attributes of the named tag when setting object properties, rather than the <code>CDATA</code> content of its child elements.</p>
<p>You can also possible to set default values for a particular configuration           variable, or mark a certain configuration variable as mandatory, through skillful           use of the <code>default</code> and <code>required</code> attributes in the definition file. Consider Listing 23, which makes the <code>length</code> and <code>width</code> configuration variables mandatory and sets a default value for the <code>height</code>:<br />
<a name="c23"><strong>Listing 23. An XJConf definition file with 'default' and 'required' constraints</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="rectangularobject" type="RectangularObject"&gt;
        &lt;attribute name="length" type="integer" required="true" /&gt;
        &lt;attribute name="width" type="integer" required="true" /&gt;
        &lt;attribute name="height" type="integer" default="10" /&gt;
    &lt;/tag&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>If you now try to read a configuration file which is missing a required value, XJConf will throw a <code>MissingAttributeException</code> (Figure 1):<br />
<a name="N10374"><strong>Figure 1. An XJConf exception thrown when a required attribute is missing</strong></a><br />
<img src="http://www.ibm.com/developerworks/xml/library/x-xjconf/image1.jpg" alt="An XJConf exception thrown when a required attribute is missing" width="572" height="374" /><br />
In previous examples, you saw that XJConf can automatically call the           appropriate setter methods to configure object instances. This automatic           invocation of setter methods depends greatly on the correct naming of the setter           methods for easy identification and mapping to element/attribute names. If you           don't like this, you can also explicitly define the setter method for each           element/attribute, with the <code>setter</code> attribute in the           definition file. Listing 24 illustrates this use of  custom setter methods for the <code>length</code> and <code>width</code> attributes:<br />
<a name="c24"><strong>Listing 24. An XJConf definition file with custom setter methods</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
    &lt;tag name="rectangularobject" type="RectangularObject"&gt;
        &lt;attribute name="length" setter="setL" /&gt;
        &lt;attribute name="width" setter="setW" /&gt;
        &lt;attribute name="height" /&gt;
    &lt;/tag&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>As you might know, a new feature in PHP 5 is the introduction of the special           <code>__set()</code> and <code>__get()</code> overloading methods, which you can use to set object  properties even if a setter or getter method is not explicitly defined  for that property. Listing 25 revises the class definition from Listing 16 to illustrate how this works in practice:<br />
<a name="c25"><strong>Listing 25. A PHP class definition with __set() and __get()</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
class RectangularObject {

    // declare properties
    public $length;
    public $height;
    public $width;

    // declare constructor
    function __construct() {
        return true;
    }

    // declare generic setter method
    public function __set($property, $value) {
        $this-&gt;$property = $value;
    }

    // declare generic getter method
    public function __get($property) {
        return $this-&gt;property;
    }

    // declare other methods
    function getVolume() {
        return ($this-&gt;length * $this-&gt;width * $this-&gt;height);
    }
}
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Assume the same data and definition files as in Listing 17 and Listing 18 respectively and try to run the PHP script in Listing 26:<br />
<a name="c26"><strong>Listing 26. A PHP script to configure an object using an XJConf configuration file</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

// load class definition
include_once 'RectangularObject.php';

// load facade
XJConfLoader::load('XJConfFacade');
$xml = new XJConfFacade();

// attach definitions to parser
$xml-&gt;addDefinition('defs.xml');

// parse XML
$xml-&gt;parse('data.xml');

// access object instance
$instance = $xml-&gt;getConfigValue('rectangularobject');
print 'The volume of the object is: ' . $instance-&gt;getVolume() . ' units';
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>You should see the following output:<br />
<a name="c27"><strong>Listing 27. The output of Listing 26</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
The volume of the object is: 3000 units
</pre>
</td>
</tr>
</tbody>
</table>
<p>You'll notice that despite the lack of explicitly-defined  setter methods in the class definition, XJConf was still able to  configure the object's properties through the <code>__set()</code> method. This feature can, again, significantly reduce the length of your  class definitions and make your application code simpler to maintain  and easier to read.</p>
<p>In versions of XJConf for PHP prior to V. 0.2.0, these special overloading           methods are not supported and attempts to use them will generate a fatal error in your PHP script.</p>
<p>Finally, you'll see that all the previous listings explicitly load the class           definition files, before parsing the XML definitions and data. XJConf can           automatically do this task for you using its own class loader as needed;           examples illustrating this feature are available in the XJConf for PHP package           (See Resources). You should definitely look at           them if you work with numerous classes in your application.</p>
<p><a name="N103F2">Project: Configure a complex class tree</a></p>
<p>As the previous listings demonstrated, XJConf can use either attributes or           child elements to correctly configure an instantiated object. In all cases but           one, therefore, it is your relative comfort level with these two techniques that           will define your approach. However, in one case, the use of  child elements           offers an advantage over attributes: When you link one or more objects to another in a complex tree.</p>
<p>To illustrate, consider Listing 28, which defines some classes:<br />
<a name="c28"><strong>Listing 28. Some PHP class definitions (App.php)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// configuration class
class Config {
    // declare properties
    private $host;
    private $port;
    private $user;
    private $pass;

    // declare methods
    function setConfig($confArray) {
        if (isset($confArray['host'])) {
            $this-&gt;host = $confArray['host'];
        }
        if (isset($confArray['port'])) {
            $this-&gt;port = $confArray['port'];
        }
        if (isset($confArray['user'])) {
            $this-&gt;user = $confArray['user'];
        }
        if (isset($confArray['pass'])) {
            $this-&gt;pass = $confArray['pass'];
        }
    }
}

// these inherit from the Config class
class DBConfig extends Config {
}

class SMTPConfig extends Config {
}

// application class
class App {
    // declare properties
    public $DBConfig;
    public $SMTPConfig;

    // declare constructor
    public function __construct() {
        return true;
    }

    // declare setter methods
    function setDBConfig($db) {
        $this-&gt;DBConfig = $db;
    }
    function setSMTPConfig($smtp) {
        $this-&gt;SMTPConfig = $smtp;
    }    

    // declare getter methods
    function getDBConfig() {
        return $this-&gt;DBConfig;
    }
    function getSMTPConfig() {
        return $this-&gt;SMTPConfig;
    }
}
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 28 begins with the <code>Config</code> class, which exposes a generic API to receive an associative array of server access parameters. The <code>DBConfig</code> and <code>SMTPConfig</code> classes are sub-classes of this <code>Config</code> class, and are intended specifically to store access parameters for a database server and an SMTP server respectively. <code>DBConfig</code> and <code>SMTPConfig</code> objects are, in turn, used by the <code>App class</code>, which represents an application. This <code>App</code> class exposes setter and getter methods to set and retrieve the corresponding <code>Config</code> class as needed.</p>
<p>Configuration of these classes occurs through an XML configuration file, such as the one in Listing 29:<br />
<a name="c29"><strong>Listing 29. An XML configuration file (conf.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version='1.0'?&gt;
&lt;configuration&gt;
  &lt;app&gt;
    &lt;db&gt;
      &lt;array&gt;
        &lt;host&gt;localhost&lt;/host&gt;
        &lt;user&gt;guest&lt;/user&gt;
        &lt;pass&gt;mysql123&lt;/pass&gt;
      &lt;/array&gt;
    &lt;/db&gt;

    &lt;smtp&gt;
      &lt;array&gt;
        &lt;host&gt;mail.domain.com&lt;/host&gt;
        &lt;user&gt;sluggo&lt;/user&gt;
        &lt;pass&gt;mypass&lt;/pass&gt;
        &lt;port&gt;25&lt;/port&gt;
      &lt;/array&gt;
    &lt;/smtp&gt;
  &lt;/app&gt;
&lt;/configuration&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>The glue needed to convert the XML data in Listing 29 into a fully-configured <code>App</code> object instance lies in the definition file (Listing 30) and the corresponding PHP script (Listing 31). Look at the definition file first:<br />
<a name="c30"><strong>Listing 30. An XJConf definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
  &lt;tag name="app" type="App"&gt;
    &lt;tag name="db" type="DBConfig" setter="setDBConfig"&gt;
        &lt;tag name="array" type="array" keyAttribute="name" setter="setConfig"&gt;
            &lt;tag name="host" type="string" /&gt;
            &lt;tag name="user" type="string" /&gt;
            &lt;tag name="pass" type="string" /&gt;
        &lt;/tag&gt;
    &lt;/tag&gt;
    &lt;tag name="smtp" type="SMTPConfig" setter="setSMTPConfig"&gt;
        &lt;tag name="array" type="array" keyAttribute="name" setter="setConfig"&gt;
            &lt;tag name="host" type="string" /&gt;
            &lt;tag name="port" type="integer" /&gt;
            &lt;tag name="user" type="string" /&gt;
            &lt;tag name="pass" type="string" /&gt;
        &lt;/tag&gt;
    &lt;/tag&gt;
  &lt;/tag&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>How does this work? It's not really as difficult as it looks:</p>
<ol>
<li>When XJConf encounters an <code>&lt;app&gt;</code> element in           the configuration file, it instantiates an <code>App</code> object           instance. From the class definitions in Listing 28, you'll           see that this <code>App</code> object exposes the <code>setDBConfig()</code> and <code>setSMTPConfig()</code> methods.</li>
<li> <a name="step2">When XJConf </a>next encounters a <code>&lt;db&gt;</code> or <code>&lt;smtp&gt;</code> element, it           instantiates a <code>DBConfig</code> or <code>SMTPConfig</code> object and invokes the <code>setConfig()</code> setter method of the object. The input to this setter method is an  array of configuration parameters, which is natively created from the <code>&lt;array&gt;</code> element and its children.</li>
<li>The <code>DBConfig</code> and <code>SMTPConfig</code> objects created in step 2 are then attached back to the <code>App</code> object through the setter methods <code>setDBConfig()</code> and <code>setSMTPConfig()</code>. You'll notice that these methods are also named in the definition file through the <code>setter</code> attribute.
<p>The resulting <code>App</code> object instance is then retrieved from within a PHP script by calling <code>getConfigValue()</code>. In a similar vein, the instantiated and configured           <code>DBConfig</code> and <code>SMTPConfig</code> objects can also be retrieved, by calling <code>App::getDBConfig()</code> or <code>App::getSMTPConfig()</code>. You can see this in Listing 31:</li>
</ol>
<p><a name="c31"><strong>Listing 31. A PHP script to configure a complex class tree</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

// include class file
include_once 'App.php';

// load facade
XJConfLoader::load('XJConfFacade');
$xml = new XJConfFacade();

// attach definitions to parser
$xml-&gt;addDefinition('defs.xml');

// parse XML
$xml-&gt;parse('conf.xml');

// access objects
$app = $xml-&gt;getConfigValue('app');
$db = $app-&gt;getDBConfig();
$smtp = $app-&gt;getSMTPConfig();

// display App object
print_r($app);
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 32 displays the output:<br />
<a name="c32"><strong>Listing 32. The output of Listing 31</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
App Object
(
    [DBConfig] =&gt; DBConfig Object
        (
            [host:private] =&gt; localhost
            [port:private] =&gt;
            [user:private] =&gt; guest
            [pass:private] =&gt; mysql123
        )

    [SMTPConfig] =&gt; SMTPConfig Object
        (
            [host:private] =&gt; mail.domain.com
            [port:private] =&gt; 25
            [user:private] =&gt; sluggo
            [pass:private] =&gt; mypass
        )

)

<a name="N10501">Project: Build a web-based           configuration interface</a>

Another common real-world requirement for many projects  is a Web-based           configuration tool, which allows users to input configuration  data through a Web           form and saves this to a file in XML format. XJConf has  limited usefulness in           this context. While the package provides a full-featured API  to read           XML-formatted configuration data into PHP data structures, it  does not offer any           methods to write data back to a file. Thus, in these  situations, it is necessary           to supplement XJConf with the DOM extension in PHP, which  provides an API to dynamically construct an XML tree and write it to a  file.

Listing 33 demonstrates the use of these two tools:

<a name="c33"><strong>Listing 33. A PHP script to edit and save configuration data to a file</strong></a>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?php
// include XJConf class file
include_once 'XJConf/XJConfLoader.php';

$dataFile = 'config.xml';
$defsFile = 'defs.xml';

// if form is not submitted
if (!isset($_POST['submit'])) {

    // check to see if config file exists
    if (file_exists($dataFile)) {

        // load facade
        XJConfLoader::load('XJConfFacade');
        $xml = new XJConfFacade();

        // attach definitions to parser
        $xml-&gt;addDefinition($defsFile);

        // parse XML
        $xml-&gt;parse($dataFile);
    }
?&gt;
&lt;html&gt;
 &lt;head&gt;&lt;basefont face="Arial"&gt;&lt;/head&gt;
 &lt;body&gt;
  &lt;h2&gt;Configuration&lt;/h2&gt;
  &lt;table border="0" cellspacing="5" cellpadding="5"&gt;
   &lt;form action="&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;" method="post"&gt;
    &lt;tr&gt;
     &lt;td&gt;POP3 host name&lt;/td&gt;
     &lt;td&gt;&lt;input type="text" name="pop3_host"
     value="&lt;?php echo (isset($xml)) ? $xml-&gt;getConfigValue('host') : null; ?&gt;"
     &gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
     &lt;td&gt;POP3 port&lt;/td&gt;
     &lt;td&gt;&lt;input type="text" name="pop3_port"
     value="&lt;?php echo (isset($xml)) ? $xml-&gt;getConfigValue('port') : null; ?&gt;"
     &gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
     &lt;td&gt;POP3 user name&lt;/td&gt;
     &lt;td&gt;&lt;input type="text" name="pop3_user"
     value="&lt;?php echo (isset($xml)) ? $xml-&gt;getConfigValue('user') : null; ?&gt;"
     &gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
     &lt;td&gt;POP3 user password&lt;/td&gt;
     &lt;td&gt;&lt;input type="text" name="pop3_pass"
     value="&lt;?php echo (isset($xml)) ? $xml-&gt;getConfigValue('pass') : null; ?&gt;"
     &gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
     &lt;td colspan="2" align="center"&gt;&lt;input type="submit" name="submit"
     value="Save Configuration"&gt;&lt;/td&gt;
    &lt;/tr&gt;
   &lt;/form&gt;
  &lt;/table&gt;
 &lt;/body&gt;
&lt;/html&gt;
&lt;?php
} else {
    // do some input validation here

    // write the submitted values to a configuration file
    // generate DOM tree and root node
    $dom = new DOMDocument('1.0', 'iso-8859-1');
    $conf = $dom-&gt;createElement('conf');
    $dom-&gt;appendChild($conf);    

    // attach child nodes
    $host = new DOMElement('host', $_POST['pop3_host']);
    $port = new DOMElement('port', $_POST['pop3_port']);
    $user = new DOMElement('user', $_POST['pop3_user']);
    $pass = new DOMElement('pass', $_POST['pop3_pass']);
    $conf-&gt;appendChild($host);
    $conf-&gt;appendChild($port);
    $conf-&gt;appendChild($user);
    $conf-&gt;appendChild($pass);

    // save to configuration file
    $dom-&gt;formatOutput = true;
    if ($dom-&gt;save($dataFile)) {
        echo 'Configuration successfully saved!';
    }
}
?&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Listing 33 is divided into two parts: a form which displays the current  configuration (if available) and allows the user to edit it, and a form  processor, which accepts the new configuration and saves it to a file.  XJConf is used in the first half of the script, to parse the XML  configuration file and retrieve its contents into PHP variables; these  variables are then used to pre-fill the fields of the Web form.</p>
<p>Listing 34 contains the simple definition file used by Listing 33:<br />
<a name="c34"><strong>Listing 34. An XJConf definition file (defs.xml)</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;defines&gt;
  &lt;tag name="host" type="string"/&gt;
  &lt;tag name="port" type="integer"/&gt;
  &lt;tag name="user" type="string"/&gt;
  &lt;tag name="pass" type="string"/&gt;
&lt;/defines&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>Once the form is submitted, the DOM extension in PHP takes over. A <code>DOMDocument</code> instance is created, and child elements are attached to it holding the  configuration values input by the user. Once the entire DOM tree has  been constructed, it's written back to the configuration file using the <code>DOMDocument::save()</code> method.</p>
<p>Figure 2 illustrates what the form looks like:<br />
<a name="N10547"><strong>Figure 2. A Web form to edit and save configuration data</strong></a><br />
<img src="http://www.ibm.com/developerworks/xml/library/x-xjconf/image2.jpg" alt="A Web form to edit and save configuration data" width="572" height="402" /><br />
And Listing 35 demonstrates one such configuration file written by this script:<br />
<a name="c35"><strong>Listing 35. An example file created by Listing 34</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>
&lt;?xml version="1.0" encoding="iso-8859-1"?&gt;
&lt;conf&gt;
  &lt;host&gt;localhost&lt;/host&gt;
  &lt;port&gt;110&lt;/port&gt;
  &lt;user&gt;joelle&lt;/user&gt;
  &lt;pass&gt;guessme&lt;/pass&gt;
&lt;/conf&gt;
</pre>
</td>
</tr>
</tbody>
</table>
<p>As the previous listings illustrate, the XJConf package  provides an           easy-to-use, flexible API that reads XML-formatted  configuration files and           converts the values found therein into PHP data structures. In  addition to           simple string and numeric values, it also supports the use of  arrays and           objects, and includes built-in intelligence to automatically  configure           newly-instantiated objects through setter methods. For all  these reasons, it's a           worthy addition to the toolkit of any PHP developer. Try it  out the next time you need a interface between your PHP application and  your XML configuration file, and see for yourself!</p>
<p><!-- CMA ID: 265194 --> <!-- Site ID: 1 --><!--XSLT stylesheet used to transform this file: dw-document-html-6.0.xsl--><br />
<a name="resources">Resources</a></p>
<p><strong>Learn</strong></p>
<ul>
<li>The <a href="http://php.xjconf.net/">XJConf for PHP</a> Web site: Find more information on the XJConf package.</li>
<li> <a href="http://www.stubbles.net/">The Stubbles project</a>: See XJConf for PHP in action. With this PHP 5 framework,  combine your favorite features from other programming languages and  frameworks. Use only  the packages you like and combine it with PEAR,  the Zend Framework or any other PHP-based framework.</li>
<li> <a href="http://php.xjconf.net/timeline">XJConf Timeline</a>: Track development and news of XJConf for PHP.</li>
<li> <a href="http://www.php.net/xmlreader">XMLReader functions</a>: Obtain instructions for to activate PHP's xmlreader extension.</li>
<li> <a href="http://pear.php.net/packages.php?catpid=22&amp;catname=XML">More PEAR packages related to PHP and XML development</a>: Find other PEAR packages related to PHP and XML development.</li>
<li> <a href="http://www.ibm.com/developerworks/xml">developerWorks XML zone</a>: Get the resources you need to advance your skills in the XML arena with articles, tutorials, forums, and more.</li>
<li> <a href="http://safari5.bvdep.com/">The technology bookstore</a>: Browse for books on these and other technical topics.</li>
<li> <a href="http://www.ibm.com/certify/certs/01001503.shtml">IBM XML certification</a>: Find out how you can become an IBM-Certified Developer in XML and related technologies.</li>
<li> <a href="http://www.ibm.com/developerworks/views/xml/library.jsp">XML technical library</a>: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.</li>
<li> <a href="http://www.ibm.com/developerworks/offers/techbriefings/?S_TACT=105AGX06&amp;S_CMP=art">developerWorks technical events and webcasts</a>: Stay current with technology in these sessions.</li>
</ul>
<p><strong>Get products and technologies</strong></p>
<ul>
<li> <a href="http://pear.php-tools.net/index.php?package=XJConfForPHP&amp;downloads"> XJConf for PHP package</a>: Download this API.</li>
<li> <a href="http://www.ibm.com/developerworks/downloads/?S_TACT=105AGX06&amp;S_CMP=tut">IBM trial software</a>: Build your next development project with trial software available for download directly from developerWorks.</li>
</ul>
<p><strong>Discuss</strong></p>
<ul>
<li><a href="http://www.ibm.com/developerworks/forums/dw_forum.jsp?forum=1080&amp;cat=11">Participate in the discussion forum</a>.</li>
<li> <a href="http://www.ibm.com/developerworks/forums/dw_xforums.jsp">XML zone discussion forums</a>: Participate in any of several XML-centered forums.</li>
<li> <a href="http://www.ibm.com/developerworks/blogs/">developerWorks blogs</a>: Check out these blogs and get involved in the <a href="http://www.ibm.com/developerworks/community">developerWorks community</a>.</li>
<li> <a href="http://www.ibm.com/developerworks/forums/dw_xforums.jsp">XML zone discussion forums</a>: Participate in any of several XML-centered forums.</li>
</ul>
</pre>
</td>
</tr>
</tbody>
</table>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/792-process-xml-configuration-files-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP cannot connect to mysql when run inside Apache</title>
		<link>http://www.doyourself.org/mysql/788-php-cannot-connect-to-mysql-when-run-inside-apache/</link>
		<comments>http://www.doyourself.org/mysql/788-php-cannot-connect-to-mysql-when-run-inside-apache/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 23:41:17 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=788</guid>
		<description><![CDATA[I ran into a very strange issue when Apache/PHP/MySQL. What happend was my php code suddenly cannot connect to mysql on another machine any more. The error message is: mysqli_connect() [function.mysqli-connect]: (HY000/2003): Can't connect to MySQL server on '218.241.156.222' (13) The strange thing was that if I connect mySQL from command line, even run the [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>I ran into a very strange issue when Apache/PHP/MySQL.<br />
What happend was my php code suddenly cannot connect to mysql on another machine any more. The error message is:</p>
<pre>mysqli_connect() [function.mysqli-connect]: (HY000/2003): Can't connect to MySQL server on '218.241.156.222' (13)</pre>
<p>The  strange thing was that if I connect mySQL from command line, even run  the same code by php directly from command line, it worked just fine.</p>
<p>After searched around, I finally found the answer. Looks like it has something to do with SELinux settings.</p>
<p>To fix the issue, I only need to run:</p>
<pre>setsebool httpd_can_network_connect_db 1</pre>
<p>Before I ran the script, the file content of /selinux/booleans/httpd_can_network_connect_db was:<br />
0 0</p>
<p>After I ran the script, content changed to:<br />
1 1</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/mysql/788-php-cannot-connect-to-mysql-when-run-inside-apache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How do I expire a PHP session after 30 minutes?</title>
		<link>http://www.doyourself.org/php/559-how-do-i-expire-a-php-session-after-30-minutes/</link>
		<comments>http://www.doyourself.org/php/559-how-do-i-expire-a-php-session-after-30-minutes/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 06:50:33 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[30]]></category>
		<category><![CDATA[a]]></category>
		<category><![CDATA[after]]></category>
		<category><![CDATA[do]]></category>
		<category><![CDATA[expire]]></category>
		<category><![CDATA[How]]></category>
		<category><![CDATA[I]]></category>
		<category><![CDATA[minutes]]></category>
		<category><![CDATA[Session]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=559</guid>
		<description><![CDATA[You should implement a session timeout on your own. Both session.gc_maxlifetime and session.cookie_lifetime are not reliable. The reason for that is: First: session.gc_maxlifetime session.gc_maxlifetime specifies the number of seconds after which data will be seen as &#8216;garbage&#8217; and cleaned up. Garbage collection occurs during session start. But the garbage collector is only started with a [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="post-text">
<p>You should implement a session timeout on your own. Both <a href="http://docs.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime" rel="nofollow"><code>session.gc_maxlifetime</code></a> and <a href="http://docs.php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime" rel="nofollow"><code>session.cookie_lifetime</code></a> are not reliable. The reason for that is:</p>
<p>First:</p>
<blockquote>
<p><strong>session.gc_maxlifetime</strong><br />
  <em>session.gc_maxlifetime</em><br />
specifies the number of seconds after which data will be seen as<br />
&#8216;garbage&#8217; and cleaned up. Garbage collection occurs during session<br />
start.</p>
</blockquote>
<p>But the garbage collector is only started with a probability of <a href="http://docs.php.net/manual/en/session.configuration.php#ini.session.gc-probability" rel="nofollow"><code>session.gc_probability</code></a> devided by <a href="http://docs.php.net/manual/en/session.configuration.php#ini.session.gc-divisor" rel="nofollow"><code>session.gc_divisor</code></a>. And using the default values for that options (1 and 100), the chance is only at 1%.</p>
<p>Furthermore the age of the session data is calculated on the fileâ€™s last modification date and not the last access date:</p>
<blockquote>
<p><strong>Note:</strong> If you are using the default<br />
file-based session handler, your filesystem must keep track of access<br />
times (atime). Windows FAT does not so you will have to come up with<br />
another way to handle garbage collecting your session if you are stuck<br />
with a FAT filesystem or any other filesystem where atime tracking is<br />
not available. Since PHP 4.2.3 it has used mtime (modified date)<br />
instead of atime. So, you won&#8217;t have problems with filesystems where<br />
atime tracking is not available.</p>
</blockquote>
<p>So it additionally might occur that a session data file is deleted while the session itself is still considered as valid.</p>
<p>And second:</p>
<blockquote>
<p><strong>session.cookie_lifetime</strong><br />
  <em>session.cookie_lifetime</em> specifies the lifetime of the cookie in seconds which is sent to the browser. [â€¦]</p>
</blockquote>
<p>This does only affect the cookie lifetime. But the session itself<br />
may be still valid. Itâ€™s the serverâ€™s task to invalidate a session, not<br />
the clientâ€™s.</p>
<p>So the best solution would be to implement a session timeout on your own:</p>
<pre><code><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_SESSION</span><span class="pun">[</span><span class="str">'CREATED'</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">&nbsp; &nbsp; $_SESSION</span><span class="pun">[</span><span class="str">'CREATED'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> time</span><span class="pun">();</span><span class="pln"></span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">time</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> $_SESSION</span><span class="pun">[</span><span class="str">'CREATED'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1800</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">&nbsp; &nbsp; </span><span class="com">// session started more than 30 minates ago</span><span class="pln">&nbsp; &nbsp; session_destroy</span><span class="pun">();</span><span class="pln">&nbsp; &nbsp; $_SESSION </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">();</span><span class="pln"></span><span class="pun">}

</span></code></pre>
<p>You can scrap sessions after a certain lifespan by using the <a href="http://uk3.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime" rel="nofollow"><code>session.gc-maxlifetime</code></a> ini setting:</p>
<p><code><span class="pln">ini_set</span><span class="pun">(</span><span class="str">'session.gc-maxlifetime'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">60</span><span class="pun">*</span><span class="lit">30</span><span class="pun">);</span><span class="pln"><br /></span></code>
<pre></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/559-how-do-i-expire-a-php-session-after-30-minutes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manipulate Zip Files with PHP</title>
		<link>http://www.doyourself.org/php/558-manipulate-zip-files-with-php/</link>
		<comments>http://www.doyourself.org/php/558-manipulate-zip-files-with-php/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 08:48:35 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[files]]></category>
		<category><![CDATA[Manipulate]]></category>
		<category><![CDATA[with]]></category>
		<category><![CDATA[ZIP]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=558</guid>
		<description><![CDATA[Back in the olden days the easiest way to create zip files using php was to have the operating system (OS) do it. Sure, there were modules you could compile php with but really affected portability. So using the OS wasnâ€™t too big of an issue but it still wasnâ€™t optimal. Zip Files The Old [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Back in the olden days the easiest way to create zip files using php<br />
was to have the operating system (OS) do it. Sure, there were modules<br />
you could compile php with but really affected portability. So using<br />
the OS wasnâ€™t too big of an issue but it still wasnâ€™t optimal. </p>
<div class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.ericlamb.net/wp-content/uploads/2009/03/zip_format.jpg"><img src="http://blog.ericlamb.net/wp-content/uploads/2009/03/zip_format-300x245.jpg" alt="Zip Files" class="size-medium wp-image-1270" height="245" width="300"></a>
<p class="wp-caption-text">Zip Files</p>
</div>
<h3>The Old Way</h3>
<p>Assuming the OS was Linux, and if you were doing php web development<br />
it probably was, youâ€™d execute a call like the below to create a<br />
gzipped archive:</p>
<div class="wp_syntax">
<div class="code">
<pre style="font-family: monospace"><span>&lt;?php</span><span>exec</span><span>(</span>tar cfvz <span>".<span>$WhereBackup</span>."</span><span>/</span><span>".<span>$Name</span>."</span><span>.</span>tar<span>.</span>gz <span>".<span>$whatBackup</span>."</span><span>)</span><span>;</span><span>?&gt;</span></pre>
</div>
</div>
<p>The above sucks for a couple reasons. For one, it requires a pretty<br />
large security hole to not be plugged; exec allows piping commands to<br />
the OS directly. For another, the above method will only work on Linux;<br />
Windows doesnâ€™t have a â€œtarâ€ command.</p>
<p>The biggest reason the above sucked, for me at least, was that the<br />
layman doesnâ€™t understand the tar.gz file extension. I canâ€™t count the<br />
number of times Iâ€™ve had to explain to a client or colleague that<br />
tar.gz is, as far as their needs go, that tar.gz is ok. â€œYou can open<br />
it in WinZip or WinRar.â€, Iâ€™d say. Sighâ€¦ </p>
<h3>Enter PclZip </h3>
<p><a href="http://www.phpconcept.net/pclzip/index.en.php" title="PclZip" target="_blank">PclZip</a><br />
is a php class that creates and manage ZIP formatted archives. PclZip<br />
works on both Windows and Linux and is pretty easy to use. Thereâ€™s a<br />
pretty extensive <a href="http://www.phpconcept.net/pclzip/man/en/index.php" target="_blank" title="PclZip User Manual">user manual</a> too.</p>
<p>I first heard about it while writing the WordPress plugin<br />
iTunes-Data. I wanted to allow the upload of the iTunes XML files but<br />
mine was over 10MB so testing was becomingâ€¦ inconvenient. I knew<br />
WordPress could manipulate zip archives so I took a look under the hood<br />
and the was PclZip.</p>
<p>Anyway, you can create zip files, remove files from existing zip<br />
files and extract zip files using the PclZip class. Below are a couple<br />
examples of how to do each.</p>
<h4>The Basics</h4>
<p>The most important thing to know about using PclZip is that the<br />
PclZip object must be instantiated with a â€œ.zipâ€ file being passed. It<br />
doesnâ€™t matter if youâ€™re creating, extracting or modifying, you have to<br />
pass the file you want to manipulate before you do anything else.</p>
<div class="wp_syntax">
<div class="code">
<pre style="font-family: monospace"><span>&lt;?php</span><span>require_once</span><span>(</span><span>'pclzip.lib.php'</span><span>)</span><span>;</span><span>$archive</span> <span>=</span> <span>new</span> PclZip<span>(</span><span>'tmp/archive.zip'</span><span>)</span><span>;</span><span>?&gt;</span></pre>
</div>
</div>
<h4>Optional Arguments</h4>
<p>PclZip allows for detailed control over archives through the use of <a href="http://www.phpconcept.net/pclzip/man/en/index.php?options" title="PclZip Optional Arguments" target="_blank">optional arguments</a> that get passed at the tail end of functions. According to the official site:</p>
<blockquote><p>
The optional arguments are identified by a name, which is in reality a<br />
static integer value. The value of the argument can be a single value<br />
or a list of values. In some cases they does not take a value, their<br />
name is enought to indicate a specific action to the method.
</p>
</blockquote>
<p>Thereâ€™s far too many arguments you can use so I wonâ€™t bother listing<br />
them all here but thereâ€™s a complete list at the end of the article.</p>
<h4>Create a Zip File</h4>
<p>To create a zip file you have to pass the name of the archive you<br />
want to create to the object. The file passed will be where to the<br />
archive will be created. </p>
<p>You can include multiple files by either passing the directory, if<br />
you want the entire directory or by using a couple different methods to<br />
pass individual files and directories; arrays or a csv string.</p>
<div class="wp_syntax">
<div class="code">
<pre style="font-family: monospace"><span>&lt;?php</span><span>require_once</span><span>(</span><span>'pclzip.lib.php'</span><span>)</span><span>;</span><span>$archive</span> <span>=</span> <span>new</span> PclZip<span>(</span><span>'tmp/archive.zip'</span><span>)</span><span>;</span>&nbsp;<span>//includes the file "debug.cl" and the directory "logs"</span><span>$files</span> <span>=</span> <span>'./debug.cl,./logs/'</span><span>;</span><span>if</span> <span>(</span><span>$archive</span><span>-&gt;</span><span>create</span><span>(</span><span>$files</span><span>)</span> <span>==</span> <span>0</span><span>)</span> <span>{</span>	<span>die</span><span>(</span><span>'Error : '</span><span>.</span><span>$archive</span><span>-&gt;</span><span>errorInfo</span><span>(</span><span>true</span><span>)</span><span>)</span><span>;</span><span>}</span><span>?&gt;</span></pre>
</div>
</div>
<p>or</p>
<div class="wp_syntax">
<div class="code">
<pre style="font-family: monospace"><span>&lt;?php</span><span>require_once</span><span>(</span><span>'pclzip.lib.php'</span><span>)</span><span>;</span><span>$archive</span> <span>=</span> <span>new</span> PclZip<span>(</span><span>'tmp/archive.zip'</span><span>)</span><span>;</span>&nbsp;<span>//same as above</span><span>$files</span> <span>=</span> <span>array</span><span>(</span><span>'./debug.cl'</span><span>,</span><span>'./logs/'</span><span>)</span><span>;</span><span>if</span> <span>(</span><span>$archive</span><span>-&gt;</span><span>create</span><span>(</span><span>$files</span><span>)</span> <span>==</span> <span>0</span><span>)</span> <span>{</span>	<span>die</span><span>(</span><span>'Error : '</span><span>.</span><span>$archive</span><span>-&gt;</span><span>errorInfo</span><span>(</span><span>true</span><span>)</span><span>)</span><span>;</span><span>}</span><span>?&gt;</span></pre>
</div>
</div>
<h4>Extracting Files from Archive</h4>
<p>There are quite a few options for extracting files from a zip<br />
archive. PclZip contains a pretty extensive filtering mechanism that<br />
allows for some pretty selective extractions.</p>
<p>By default when extracting the files from an archive PclZip puts the files relative to where the script is executed.</p>
<div class="wp_syntax">
<div class="code">
<pre style="font-family: monospace"><span>$archive</span> <span>=</span> <span>new</span> PclZip<span>(</span><span>'tmp/archive.zip'</span><span>)</span><span>;</span><span>if</span> <span>(</span><span>$archive</span><span>-&gt;</span><span>extract</span><span>(</span><span>)</span> <span>==</span> <span>0</span><span>)</span> <span>{</span>	<span>die</span><span>(</span><span>"Error : "</span><span>.</span><span>$archive</span><span>-&gt;</span><span>errorInfo</span><span>(</span><span>true</span><span>)</span><span>)</span><span>;</span><span>}</span></pre>
</div>
</div>
<p>You can explicitly state where the archive files are extracted by<br />
setting a value to the â€œPCLZIP_OPT_PATHâ€ parameter. The below extracts<br />
all the files to the â€œ./tmpâ€ directory:</p>
<div class="wp_syntax">
<div class="code">
<pre style="font-family: monospace"><span>$archive</span> <span>=</span> <span>new</span> PclZip<span>(</span><span>'tmp/archive.zip'</span><span>)</span><span>;</span><span>if</span> <span>(</span><span>$archive</span><span>-&gt;</span><span>extract</span><span>(</span>PCLZIP_OPT_PATH<span>,</span> <span>"./tmp"</span><span>)</span> <span>==</span> <span>0</span><span>)</span> <span>{</span>	<span>die</span><span>(</span><span>"Error : "</span><span>.</span><span>$archive</span><span>-&gt;</span><span>errorInfo</span><span>(</span><span>true</span><span>)</span><span>)</span><span>;</span><span>}</span></pre>
</div>
</div>
<h3>Optional Argument List</h3>
<p><a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_path" target="_blank" title="PclZip PCLZIP_OPT_PATH">PCLZIP_OPT_PATH</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_add_path" target="_blank" title="PclZip PCLZIP_OPT_ADD_PATH">PCLZIP_OPT_ADD_PATH</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_remove_path" target="_blank" title="PclZip PCLZIP_OPT_REMOVE_PATH">PCLZIP_OPT_REMOVE_PATH</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_remove_all_path" target="_blank" title="PclZip PCLZIP_OPT_REMOVE_ALL_PATH">PCLZIP_OPT_REMOVE_ALL_PATH</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_set_chmod" target="_blank" title="PclZip PCLZIP_OPT_SET_CHMOD">PCLZIP_OPT_SET_CHMOD</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_by_name" target="_blank" title="PclZip PCLZIP_OPT_BY_NAME">PCLZIP_OPT_BY_NAME</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_by_ereg" target="_blank" title="PclZip PCLZIP_OPT_BY_EREG">PCLZIP_OPT_BY_EREG</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_by_preg" target="_blank" title="PclZip PCLZIP_OPT_BY_PREG">PCLZIP_OPT_BY_PREG</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_by_index" target="_blank" title="PclZip PCLZIP_OPT_BY_INDEX">PCLZIP_OPT_BY_INDEX</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_extract_as_string" target="_blank" title="PclZip PCLZIP_OPT_EXTRACT_AS_STRING">PCLZIP_OPT_EXTRACT_AS_STRING</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_extract_in_output" target="_blank" title="PclZip PCLZIP_OPT_EXTRACT_IN_OUTPUT">PCLZIP_OPT_EXTRACT_IN_OUTPUT</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_no_compression" target="_blank" title="PclZip PCLZIP_OPT_NO_COMPRESSION">PCLZIP_OPT_NO_COMPRESSION</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_comment" target="_blank" title="PclZip PCLZIP_OPT_COMMENT">PCLZIP_OPT_COMMENT</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_add_comment" target="_blank" title="PclZip PCLZIP_OPT_ADD_COMMENT">PCLZIP_OPT_ADD_COMMENT</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_prepend_comment" target="_blank" title="PclZip PCLZIP_OPT_PREPEND_COMMENT">PCLZIP_OPT_PREPEND_COMMENT</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_replace_newer" target="_blank" title="PclZip PCLZIP_OPT_REPLACE_NEWER">PCLZIP_OPT_REPLACE_NEWER</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_extract_dir_restriction" target="_blank" title="PclZip PCLZIP_OPT_EXTRACT_DIR_RESTRICTION">PCLZIP_OPT_EXTRACT_DIR_RESTRICTION</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_add_temp_file_on" target="_blank" title="PclZip PCLZIP_OPT_ADD_TEMP_FILE_ON">PCLZIP_OPT_ADD_TEMP_FILE_ON</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_add_temp_file_on" target="_blank" title="PclZip PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD">PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD</a><br />
<a href="http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_opt_add_temp_file_on" target="_blank" title="PclZip PCLZIP_OPT_ADD_TEMP_FILE_OFF">PCLZIP_OPT_ADD_TEMP_FILE_OFF</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/558-manipulate-zip-files-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to unzip ZIP files with PHP</title>
		<link>http://www.doyourself.org/php/557-how-to-unzip-zip-files-with-php/</link>
		<comments>http://www.doyourself.org/php/557-how-to-unzip-zip-files-with-php/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 08:47:54 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[files]]></category>
		<category><![CDATA[How]]></category>
		<category><![CDATA[to]]></category>
		<category><![CDATA[unzip]]></category>
		<category><![CDATA[with]]></category>
		<category><![CDATA[ZIP]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=557</guid>
		<description><![CDATA[How to automatically unzip uploaded zip files with PHP I wanted to upload a zip file with php script and unzip it within the server running PHP and linux. How to do it? i am documenting here about a solution to unpack uploaded zip files locally within the server with PHP. well! it can be [...]]]></description>
			<content:encoded><![CDATA[<p></p><h2>How to automatically unzip uploaded zip files with PHP</h2>
<p>I wanted to upload a zip file with php script and unzip it within<br />
the server running PHP and linux. How to do it? i am documenting here<br />
about a solution to unpack uploaded zip files locally within the server<br />
with PHP. </p>
<p>well! it can be done in 3 ways. I </p>
<p>1. Using <a href="http://www.php.net/function.exec">PHP exec</a> command<br />
2. <a href="http://suphp.org/">suPHP</a> (Alternative to PHPsuexec)<br />
3. Get <a href="http://www.phpconcept.net/pclzip/index.en.php">Pclzip class</a> library. (create and extract ZIP files<br />
4. Using <a href="http://in.php.net/manual/en/zip.installation.php">Zziplib</a> with PHP</p>
<p>I was successful with (3) option.</p>
<p>I tried the first option of using <strong><a href="http://www.php.net/function.exec">php exec</a></strong> command calling system level but it never worked for me and it just kept getting checkdir errors in my apache log.</p>
<p></p>
<ol class="dp-c" start="1">
<li class="alt"><span><span>&lt;?php&nbsp;&nbsp;</span></span></li>
<li class=""><span><span class="comment">//&nbsp;uses&nbsp;&nbsp;unzip&nbsp;command&nbsp;just&nbsp;like&nbsp;in&nbsp;commandline</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="comment">//</span><span>&nbsp;&nbsp;</span></span></li>
<li class=""><span><span class="comment">//</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span><span class="func">echo</span><span>&nbsp;system(</span><span class="string">&#8216;unzip&nbsp;uploads/test.zip&#8217;</span><span>,</span><span class="vars">$output</span><span>);&nbsp;&nbsp;</span></span></li>
<li class=""><span>print_r(<span class="vars">$output</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;</span></li>
<li class=""><span>?&gt;&nbsp; <br /></span></li>
</ol>
<p>checkdir error:  cannot create ithemex<br />
                 unable to process xtheme/images/mini-archive.gif.<br />
checkdir error:  cannot create ithemex<br />
                 unable to process itheme-x/images/mini-archive.png.</p>
<p><strong>Using suPHP</strong></p>
<p>suPHP is a good method just because instead of apache running as<br />
nobody/apache it runs under user account ownership. Basically what this<br />
means that it will have no problem with file permissions for zip files.<br />
Another great advantage of suphp is security (it restricts local users<br />
reading php files). </p>
<p>Unfortunately i couldnt use suphp because it needs PHP to be running as CGI, but mine was apache module. I couldnt use suPHP</p>
<p><strong>Using Pclzip class for Zip files</strong></p>
<p>This method worked best for me. I uploaded a zip and it cleanly unpacked within my server. Just download the <a href="http://www.phpconcept.net/pclzip/index.en.php">pclzip class library</a>.<br />
Set the folder permissions to 755 where you are unpacking the files. It<br />
need not be 777. If that 755 doesnt work set the ownership and<br />
usergroup to apache or nobody. </p>
<p>Now upload a sample zip file test.zip and put the following code in php file</p>
<p></p>
<ol class="dp-c" start="1">
<li class="alt"><span><span>&lt;?php&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;<span class="keyword">require_once</span><span>(</span><span class="string">&#8216;pclzip.lib.php&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;<span class="vars">$archive</span><span>&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;PclZip(</span><span class="string">&#8216;test.zip&#8217;</span><span>);&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;<span class="keyword">if</span><span>&nbsp;((</span><span class="vars">$v_result_list</span><span>&nbsp;=&nbsp;</span><span class="vars">$archive</span><span>-&gt;extract(PCLZIP_OPT_PATH,&nbsp;</span><span class="string">&#8216;uploads&#8217;</span><span>))&nbsp;==&nbsp;0)&nbsp;{&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="keyword">die</span><span>(</span><span class="string">&#8220;Error&nbsp;:&nbsp;&#8221;</span><span>.</span><span class="vars">$archive</span><span>-&gt;errorInfo(true));&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;}&nbsp;&nbsp;</span></li>
<li class="alt"><span>&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="string">&#8220;&lt;pre&gt;&#8221;</span><span>;&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;var_dump(<span class="vars">$v_result_list</span><span>);&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="string">&#8220;&lt;/pre&gt;&#8221;</span><span>;&nbsp;&nbsp;</span></span></li>
<li class=""><span>&gt; <br /></span></li>
</ol>
<p>
<p>PCLZIP_OPT_PATH, â€˜uploadsâ€™ -&gt; is the destination unzip folder (give it 777 or 755 permissions)</p>
<p>Just the php script and you will see error codes if any. In my case it worked perfectly fine unpacking the zip file. Refer to <a href="http://www.phpconcept.net/pclzip/index.en.php">Pclzip documentation</a>.</p>
<p><code><strong>Note:</strong> You must have Zlib support installed for this script to work.<br />
To install Zlib with PHP just do <strong>yum install zlib zip php-zip</strong></code><br />
<img src="http://corpocrat.com/wp-content/uploads/2008/10/zlibsupp.GIF" alt="zlibsupp.GIF"></p>
<p>Dont forget to check apache logs to trace the exact error!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/557-how-to-unzip-zip-files-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Perfect PHP Pagination</title>
		<link>http://www.doyourself.org/php/499-perfect-php-pagination/</link>
		<comments>http://www.doyourself.org/php/499-perfect-php-pagination/#comments</comments>
		<pubDate>Wed, 12 Aug 2009 10:12:02 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Pagination]]></category>
		<category><![CDATA[Perfect]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=499</guid>
		<description><![CDATA[Pagination is a topic that has been done to death &#8212; dozens of articles and reference classes can be found for the management of result sets &#8230; however (and you knew there was a &#8220;however&#8221; coming there, didn&#8217;t you?) I&#8217;ve always been disgruntled with the current offerings to date. In this article I offer an [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><strong>Pagination is a topic that has been done to death &#8212; dozens<br />
of articles and reference classes can be found for the management of<br />
result sets &#8230; however (and you knew there was a &#8220;however&#8221; coming<br />
there, didn&#8217;t you?) I&#8217;ve always been disgruntled with the current<br />
offerings to date. In this article I offer an improved solution.</strong></p>
<p>Some pagination classes require parameters, such as a database<br />
resource and an SQL string or two, to be passed to the constructor.<br />
Classes that utilize this approach are lacking in flexibility &#8211; what if<br />
you require a different formatting of page numbers at the top and<br />
bottom of your pages, for example? Do you then have to modify some<br />
output function, or subclass the entire class, just to override that<br />
one method? These potential &#8220;solutions&#8221; are restrictive and don&#8217;t<br />
encourage code reuse.</p>
<p>This tutorial is an attempt to further abstract a class for managing<br />
result pagination, thereby removing its dependencies on database<br />
connections and SQL queries. The approach I&#8217;ll discuss provides a<br />
measure of flexibility, allowing the developer to create his or her<br />
very own page layouts, and simply register them with the class through<br />
the use of an object oriented design pattern known as the Strategy<br />
Design Pattern.</p>
<h5>What Is the Strategy Design Pattern?</h5>
<p>Consider the following: you have on your site a handful of web pages<br />
for which the results of a query are paged. Your site uses a function<br />
or class that handles the retrieval of your results and the publishing<br />
of your paged links.</p>
<p>This is all well and good until you decide to change the layout of<br />
the paged links on one (or all) of the pages. In doing so, you&#8217;re most<br />
likely going to have to modify the method to which this responsibility<br />
was delegated. </p>
<div class="vertical">
<div class="ad"><a href="http://ads.aws.sitepoint.com/phpadsnew/www/delivery/ck.php?oaparams=2__bannerid=1021__zoneid=87__cb=3ea396095e__maxdest=http://order.1and1.com/xml/order/Hosting?ac=OM.US.USa09K16337B7023a" target="_top"><img src="http://i2.sitepoint.com/images/ads/banner2_300x250_5.gif" alt="1and1.com" border="0"></a>
<div><img src="http://ads.aws.sitepoint.com/phpadsnew/www/delivery/lg.php?bannerid=1021&amp;campaignid=568&amp;zoneid=87&amp;loc=http%3A%2F%2Fads.aws.sitepoint.com%2Fadjs.php%3Fregion%3D87%26did%3Dadz%26adtype%3Dvertical&amp;referer=http%3A%2F%2Fwww.sitepoint.com%2Farticle%2Fperfect-php-pagination%2F&amp;cb=3ea396095e" alt="" style="width: 0px;height: 0px" height="0" width="0"></div>
</div>
</div>
<p>A better solution would be to create as many layouts as you like,<br />
and dynamically choose the one you desire at runtime. The Strategy<br />
Design Pattern allows you to do this. In a nutshell, the Strategy<br />
Design Pattern is an object oriented design pattern used by a class<br />
that wants to swap behavior at run time.</p>
<p>Using the polymorphic capabilities of PHP, a container class (such<br />
as the Paginated class that we&#8217;ll build in this article) uses an object<br />
that implements an interface, and defines concrete implementations for<br />
the methods defined in that interface. </p>
<p>While an interface cannot be instantiated, it can reference<br />
implementing classes. So when we create a new layout, we can let the<br />
strategy or interface within the container (the Paginated class)<br />
reference the layouts dynamically at runtime. Calls that produce the<br />
paged links will therefore produce a page that&#8217;s rendered with the<br />
currently referenced layout.</p>
<h5>Required Files</h5>
<p>As I mentioned, this tutorial is not about the mechanics of how<br />
results are paged, but how to use an interface to implement this logic<br />
while retaining flexibility. I&#8217;ve provided as a starting point a class<br />
that contains functionality for registering primitive arrays or objects<br />
- the Paginated class &#8212; as well as an interface that all of our page<br />
layouts must implement (<code>PageLayout</code>) and an implementation for a page layout (<code>DoubleBarLayout</code>). And all <a href="http://www.doyourself.org/examples/paginated-demo.zip"> <span class="sublink">the code we&#8217;ll use in the article is available for download</span></a>.</p>
<h5>A Basic Example</h5>
<p>The following examples use an array of strings. Here&#8217;s my data set:</p>
<ul>
<li>Andrew</li>
<li>Bernard</li>
<li>Castello</li>
<li>Dennis</li>
<li>Ernie</li>
<li>Frank</li>
<li>Greg</li>
<li>Henry</li>
<li>Isac</li>
<li>Jax</li>
<li>Kester</li>
<li>Leonard</li>
<li>Matthew</li>
<li>Nigel</li>
<li>Oscar</li>
</ul>
<p>However, this code could easily be extended to use an array of<br />
integers, characters, or other objects that have been fetched from a<br />
previous database call. </p>
<p>Here&#8217;s how we&#8217;d use the <code>Paginated</code> class:</p>
<p><code>&lt;?php <br />
require_once "Paginated.php"; </p>
<p>//create an array of names in alphabetic order <br />
$names = array("Andrew", "Bernard", "Castello", "Dennis", "Ernie",<br />
Frank", &nbsp; Greg", "Henry", "Isac", "Jax", "Kester", "Leonard",<br />
"Matthew", "Nigel", "Oscar"); <br />
 &nbsp; <br />
$pagedResults = new Paginated($names, 10, 1); <br />
 &nbsp; <br />
echo "&lt;ul&gt;"; <br />
 &nbsp; <br />
while($row = $pagedResults-&gt;fetchPagedRow()) { <br />
 &nbsp;echo "&lt;li&gt;{$row}&lt;/li&gt;"; <br />
} <br />
 &nbsp; <br />
echo "&lt;/ul&gt;"; <br />
?&gt;</code></p>
<p>First, we include the <code>Paginated</code> class and register an array with the constructor. The constructor takes three arguments, the final two of which are optional:</p>
<ol>
<li>The first parameter is the array of items to display<br />
&#8211; as I mentioned, these can be primitive data types or more complex<br />
objects.</li>
<p>
<li>The second parameter is the number of results we want to display on a page. By default, this figure is set to ten.</li>
<p>
<li>The third parameter is the current page number.</li>
</ol>
<p>In the above example, we&#8217;ve used the constant <code>1</code> to<br />
specify &#8220;page 1&#8243;, however you&#8217;re probably going to want to pass this as<br />
a parameter from the query string (more on this later). If an invalid<br />
page is supplied to the constructor, the page will default to 1.</p>
<p>By calling the <code>fetchPagedRow</code> method from within the<br />
while loop, our code iterates through the array, printing out the first<br />
ten names in the list (in this example, &#8220;Kester&#8221;, &#8220;Leonard&#8221;, &#8220;Matthew&#8221;,<br />
&#8220;Nigel&#8221; and &#8220;Oscar&#8221; would be omitted). These items should be included<br />
on page two, but, as the image below illustrates, there are no links to<br />
page two yet! While <code>Paginated</code> will manage the access to<br />
any object registered by the programmer, the responsibility of<br />
publishing paged links is delegated to a class that implements the <code>PageLayout</code> interface.</p>
</p>
<p><img src="http://i2.sitepoint.com/graphics/basic_example.png" alt="The rendered list doesn't offer a link to page 2" height="212" width="195"></p>
<p>Let&#8217;s add some code to display the page numbers, then we&#8217;ll dig a<br />
little deeper into the interior workings and flexibility of this class.</p>
<p>Create a new file with a PHP extension that contains the following code:</p>
<p><code>&lt;?php <br />
require_once "Paginated.php"; <br />
require_once "DoubleBarLayout.php"; </p>
<p>//create an array of names in alphabetic order <br />
$names = array("Andrew", "Bernard", "Castello", "Dennis", "Ernie",<br />
"Frank", "Greg", "Henry", "Isac", "Jax", "Kester", "Leonard",<br />
"Matthew", "Nigel", "Oscar"); </p>
<p>$page = $_GET['page']; </p>
<p>$pagedResults = new Paginated($names, 10, 1); </p>
<p>echo "&lt;ul&gt;"; </p>
<p>while($row = $pagedResults-&gt;fetchPagedRow()) { <br />
 &nbsp;echo "&lt;li&gt;{$row}&lt;/li&gt;"; <br />
} </p>
<p>echo "&lt;/ul&gt;"; </p>
<p>$pagedResults-&gt;setLayout(new DoubleBarLayout()); <br />
echo $pagedResults-&gt;fetchPagedNavigation(); <br />
?&gt;</code></p>
<p>When we run the above script now, we&#8217;ll see a list of the first ten<br />
names, as well as some additional orientation information shown in the<br />
image below. Our script now displays the text &#8220;Page 1&#8243;, as well as a<br />
link to the second page that reads &#8220;next &gt;&#8221;.</p>
<p><img src="http://i2.sitepoint.com/graphics/basic_example_paged.png" alt="The updated list includes page links" height="213" width="425"></p>
<p>In the code snippet above, we&#8217;ve made use of a class called <code>DoubleBarLayout</code>, which implements the interface <code>PageLayout</code> and contains an implementation of the <code>fetchPagedLinks</code> method. This method takes two parameters: the <code>Pagination</code> object, and the query parameters that we want to attach to the hyperlinks (if any).</p>
<p>The great thing about this method is that it takes advantage of<br />
PHP&#8217;s polymorphic capabilities, allowing the strategy that&#8217;s currently<br />
registered to be called. It&#8217;s therefore important for us to set the<br />
strategy first, before calling the method. Setting the strategy is done<br />
via a call to the setter method <code>setLayout</code>, which takes as a parameter an object that implements the <code>PageLayout</code> interface.</p>
<p>Hover over one of these links, and you&#8217;ll notice that the parameter<br />
page and its value of 2 are included in the URL page number. However,<br />
in its current state, if you click this link to the second page, the<br />
names that we would expect to be rendered will not be displayed.</p>
<p>Let&#8217;s see why this is the case by revisiting the constructor of <code>Paginated</code>. </p>
<p>The constructor takes three parameters: </p>
<ol>
<li>the array of primitive variables or objects to be processed</li>
<p>
<li>the number of records to display</li>
<p>
<li>the page number</li>
</ol>
<p>Because the method <code>fetchPagedNavigation</code> writes a query parameter, we can replace our hardcoded value of <code>1</code> with the value held in <code>$_GET['page']</code>. This way, if the user manually modifies the value in the URL to something that&#8217;s invalid, <code>Paginated</code> will default the page number to <code>1</code>. How you choose to validate your <code>GET</code> parameters is up to you, though, so I won&#8217;t dwell on this issue any further.</p>
<p><strong><em>Flexibility in Page Layout Schemes</em></strong></p>
<p>The flexibility of this class is accomplished via the <code>PageLayout</code> interface, which is part of the Paginated object. The <code>PageLayout</code> interface can reference any object that implements it, and calls to the <code>Paginated</code> method <code>fetchPagedNavigation</code><br />
will cause the currently registered object to be referenced. If you<br />
haven&#8217;t used interfaces before, this may seem a little confusing, but<br />
basically the end result is that the correct code will be called, and<br />
our results will be correctly spread over multiple pages. </p>
<p>To implement this technique, all you need to do is create a layout strategy that implements the <code>PageLayout</code> interface. Then, provide an implementation for the method <code>fetchPagedLinks</code>.</p>
<p>This method takes two parameters:</p>
<ol>
<li><code>$parent</code>, which is the <code>Paginated</code> object</li>
<p>
<li><code>$queryVars</code>, which is the list of query parameters to append to the page numbers (and is optional)</li>
</ol>
<p>There are three important points to note here: </p>
<ol>
<li>You&#8217;ll never be making direct calls to <code>fetchPagedLinks</code>. All methods of <code>Paginated</code> can be accessed through the parent object.</li>
<p>
<li>If you want to use your own page layouts, you must change the layout of the paginated result via calls to <code>setLayout</code>.</li>
</ol>
<p>With those points in mind, let&#8217;s create our own page layout! We&#8217;ll call it <code>TrailingLayout</code>. Here&#8217;s the code:</p>
<p><code>&lt;?php <br />
class TrailingLayout implements PageLayout { </p>
<p> &nbsp;public function fetchPagedLinks($parent, $queryVars) { <br />
 &nbsp; <br />
 &nbsp; &nbsp;$currentPage = $parent-&gt;getPageNumber(); <br />
 &nbsp; &nbsp;$totalPages = $parent-&gt;fetchNumberPages(); <br />
 &nbsp; &nbsp;$str = ""; </p>
<p> &nbsp; &nbsp;if($totalPages &gt;= 1) { <br />
 &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;for($i = 1; $i &lt;= $totalPages; $i++) { <br />
 &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;$str .= " &lt;a href="?page={$i}$queryVars"&gt;Page $i&lt;/a&gt;"; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;$str .= $i != $totalPages ? " | " : ""; <br />
 &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp;} </p>
<p> &nbsp; &nbsp;return $str; <br />
 &nbsp;} <br />
} <br />
?&gt;</code></p>
<p>The above class, <code>TrailingLayout</code>, implements the <code>PageLayout</code> interface, and provides implementation for <code>fetchPagedLinks</code>. Remember the parameter <code>$parent</code> is an instance of the <code>Paginated</code> object, so we can determine the current page, and the total number of pages, by making calls to <code>getPageNumber</code> and <code>fetchNumberPages</code>, respectively.</p>
<p>In this simple layout, once there&#8217;s more than a single page, the<br />
script will loop through the array of pages, and create a hyperlink and<br />
page number for each one. The <code>$queryVars</code> are also written to the <code>href</code> as part of this loop; the parameter <code>$queryVars</code> comes in handy when we&#8217;re paging the results of a search that may have included a few parameters.</p>
<p>Note that the string <code>"Page"</code> is not a part of the <code>queryVars</code>, but is written by the loop that appends the page numbers to the string.</p>
<p>Now let&#8217;s try implementing our new layout:</p>
<p><code>&lt;?php <br />
require_once "Paginated.php"; <br />
//include your customized layout <br />
require_once "TrailingLayout.php"; </p>
<p>//create an array of names in alphabetic order. A database call could have retrieved these items <br />
$names = array("Andrew", "Bernard", "Castello", "Dennis", "Ernie",<br />
"Frank", "Greg", "Henry", "Isac", "Jax", "Kester", "Leonard",<br />
"Matthew", "Nigel", "Oscar"); </p>
<p>$page = $_GET['page']; </p>
<p>$pagedResults = new Paginated($names, 10, $page); </p>
<p>echo "&lt;ul&gt;"; </p>
<p>while($row = $pagedResults-&gt;fetchPagedRow()) { <br />
 &nbsp;echo "&lt;li&gt;{$row}&lt;/li&gt;"; <br />
} </p>
<p>echo "&lt;/ul&gt;"; </p>
<p>//$pagedResults-&gt;setLayout(new TrailingLayout()); <br />
echo $pagedResults-&gt;fetchPagedNavigation("&amp;firstLetter=l"); <br />
?&gt;</code></p>
<p>If we were to run the script above as is, we&#8217;d get the following error message:</p>
<p><code>"Fatal error: Call to a member function fetchPagedLinks() on a non-object".</code></p>
<p>This error occurs because we haven&#8217;t yet registered the strategy that we wish to use before calling <code>fetchPagedNavigation</code>. To change the layout of the paged links, we pass to the <code>setLayout</code> method a parameter, which can be any object that implements the <code>PageLayout</code> interface. In the code from our <code>TrailingLayout</code> example above, uncomment the second-last line of PHP code, and refresh your page to see the final result, shown below.</p>
<p><img src="http://i2.sitepoint.com/graphics/trailing_layout_with_param.png" alt="The finished list" height="225" width="209"></p>
<p>The last line in that code demonstrates how the <code>fetchPagedNavigation</code> method can take an optional parameter string to define the rest of the query (note the inclusion of the ampersand before the <code>firstLetter</code> parameter in the URL to distinguish it from the page parameter).</p>
<h5>Summary</h5>
<p>In this article, I introduced the Strategy Design Pattern, which can<br />
be used to provide flexibility when you&#8217;re laying out paged links.</p>
<p>We saw this pattern in action through the <code>Paginated</code><br />
class, which will hopefully prove useful to you when you&#8217;re displaying<br />
data across multiple pages. The class can be used to display arrays<br />
containing primitive data types or more complex objects.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/499-perfect-php-pagination/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to get a page&#8217;s Google PageRank (PR) with PHP</title>
		<link>http://www.doyourself.org/php/241-how-to-get-a-pages-google-pagerank-pr-with-php-2/</link>
		<comments>http://www.doyourself.org/php/241-how-to-get-a-pages-google-pagerank-pr-with-php-2/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 10:28:33 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[(PR)]]></category>
		<category><![CDATA[a]]></category>
		<category><![CDATA[Get]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[How]]></category>
		<category><![CDATA[page's]]></category>
		<category><![CDATA[PageRank]]></category>
		<category><![CDATA[to]]></category>
		<category><![CDATA[with]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=241</guid>
		<description><![CDATA[I was recently looking for an easy way to lookup the Page Rank for a given page, site or really any URL. I&#039;ve seen lots of tools out that that can do it, and many of them allow you to integrate the tool into your site. But those require a lot of extra work, and [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>I was recently looking for an easy way to lookup the Page Rank for a given page, site or really any URL. I&#039;ve seen lots of tools out that that can do it, and many of them allow you to integrate the tool into your site. But those require a lot of extra work, and they just really display the PR. I wanted to actually retrieve the value with PHP. Doing a quick search on google revealed a <a href="http://www.phpclasses.org/browse/package/2682.html">Google PageRank class</a> from phpclasses.org. It seems to be pretty robust, and it looks like it will do the job!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/241-how-to-get-a-pages-google-pagerank-pr-with-php-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Determine a visitor&#8217;s location by their IP address!</title>
		<link>http://www.doyourself.org/php/242-determine-a-visitors-location-by-their-ip-address-3/</link>
		<comments>http://www.doyourself.org/php/242-determine-a-visitors-location-by-their-ip-address-3/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 10:28:33 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[a]]></category>
		<category><![CDATA[address!]]></category>
		<category><![CDATA[by]]></category>
		<category><![CDATA[Determine]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[location]]></category>
		<category><![CDATA[their]]></category>
		<category><![CDATA[visitor's]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=242</guid>
		<description><![CDATA[Tracking a visitor&#039;s geographical location (ie. country, region, city, latitude, longitude, ZIP code, ISP and domain name) used to be a cool trick. Now it is an integral part of many websites, enabling them to identify the locations from where they&#039;re getting the maximum traffic; and tune your webpages accordingly. It also enables you to [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Tracking a visitor&#039;s geographical location (ie. country, region, city, latitude, longitude, ZIP code, ISP and domain name) used to be a cool trick. Now it is an integral part of many websites, enabling them to identify the locations from where they&#039;re getting the maximum traffic; and tune your webpages accordingly. It also enables you to modify the site according to location, or send users to specific sections (ie. show prices in CAD for Canadian visitors).</p>
<p>It is relatively easy to use this technology on your website with IP2Location&#039;s proprietary IP address lookup database. This database is free for the IP-Country version. Of you need more details like region, city, latitude, longitude, ZIP code, ISP and domain name for the IP address, you need to purchase the full database.<span></span></p>
<p>To determine the user&#039;s location by their IP address, you need to perform these three steps:</p>
<p>1. Retrieve the visitors&#039; IP address <br />
Here are the <a target="_blank" href="http://www.justin-cook.com/wp/2006/11/28/how-to-retrieve-a-visitors-ip-address/">functions to get the IP address using ASP, PHP, an .Net (C# &#038; VB.Net)</a>.</p>
<p>2. Convert the visitor&#039;s IP address to an IP Number<br />
Here are the <a target="_blank" href="http://www.justin-cook.com/wp/2006/11/28/convert-an-ip-address-to-ip-number-with-php-asp-c-and-vbnet/">functions to convert an IP address to an IP number using ASP, PHP, an .Net (C# &#038; VB.Net)</a>.</p>
<p>3. Locate the IP Number in the IP-Country database<br />
Example: the IP Address 202.186.13.4 converts to IP Number 3401190660. It is between the beginning and the ending of the following IP numbers:<br />
&#034;3401056256&#034;,&#034;3401400319&#034;,&#034;MY&#034;,&#034;MALAYSIA&#034;</p>
<p>From the IP-Country recordset, the Country_Name with this IP number range is Malaysia, the Country_Code is MY.</p>
<p>So once you have the IP Number, here&#039;s the SQL Query to locate the matching recordset:</p>
<p><span class="kw1">SELECT</span> country_name <span class="kw1">FROM</span> ip_to_country <span class="kw1">WHERE</span> <br />
<span class="br0">&#091;</span>your IP number<span class="br0">&#093;</span> <span class="kw1">BETWEEN</span> ip_start <span class="kw1">AND</span> ip_end</p>
<p>Of course, you need to download the <a rel="external nofollow" href="http://ip-to-country.webhosting.info/downloads/ip-to-country.csv.zip">IP2Country database</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/242-determine-a-visitors-location-by-their-ip-address-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to retrieve a visitor&#8217;s IP address</title>
		<link>http://www.doyourself.org/php/243-how-to-retrieve-a-visitors-ip-address-2/</link>
		<comments>http://www.doyourself.org/php/243-how-to-retrieve-a-visitors-ip-address-2/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 10:28:33 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[a]]></category>
		<category><![CDATA[address!]]></category>
		<category><![CDATA[How]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[Retrieve]]></category>
		<category><![CDATA[to]]></category>
		<category><![CDATA[visitor's]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=243</guid>
		<description><![CDATA[Every visitor to your site or web application has an IP address. It is quite handy to be able to get that address. It can be used for security logging, or perhaps tracing. It can also be used to determine where they are in the world, or at least where their ISP is. The difficulty [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Every visitor to your site or web application has an IP address. It is quite handy to be able to get that address. It can be used for security logging, or perhaps tracing. It can also be used to determine where they are in the world, or at least where their ISP is. </p>
<p>The difficulty is when they&#039;re behind a proxy of some sort, you only see the IP address of the proxy server. So, here are the code snippets in PHP, ASP and .Net that first check for an IP addresses that&#039;s forwarded from behind a proxy, and if there&#039;s none then just get the IP address.<br />
<span></span><br />
Here it is in PHP</p>
<p><span class="kw2">&lt;?</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#040;</span><a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">&#040;</span>HTTP_X_FORWARDED_FOR<span class="br0">&#041;</span><span class="br0">&#041;</span> <span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$ip_address</span> = <a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">&#040;</span>HTTP_X_FORWARDED_FOR<span class="br0">&#041;</span>; <br />
&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$ip_address</span> = <a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">&#040;</span>REMOTE_ADDR<span class="br0">&#041;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="kw2">?&gt;</span></p></blockquote>
<p>And here&#039;s how to get the IP address in ASP</p>
<p><span class="kw2">&lt;%</span><br />
&nbsp; &nbsp; ip_address = <span class="kw1">Request</span>.<span class="kw3">ServerVariables</span><span class="br0">&#040;</span><span class="st0">&#034;HTTP_X_FORWARDED_FOR&#034;</span><span class="br0">&#041;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> ip_address = <span class="st0">&#034;&#034;</span> <span class="kw1">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ip_address = <span class="kw1">Request</span>.<span class="kw3">ServerVariables</span><span class="br0">&#040;</span><span class="st0">&#034;REMOTE_ADDR&#034;</span><span class="br0">&#041;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span> <span class="kw1">if</span><br />
<span class="kw2">%&gt;</span></p>
<p>And here&#039;s the IP retriever with proxy detection in .Net (C#)</p>
<p>public <span class="kw4">string</span> IpAddress<span class="br0">&#040;</span><span class="br0">&#041;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">string</span> strIpAddress;<br />
&nbsp; &nbsp; strIpAddress = Request.<span class="me1">ServerVariables</span><span class="br0">&#091;</span><span class="st0">&#034;HTTP_X_FORWARDED_FOR&#034;</span><span class="br0">&#093;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#040;</span>strIpAddress == <span class="kw2">null</span><span class="br0">&#041;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;strIpAddress = Request.<span class="me1">ServerVariables</span><span class="br0">&#091;</span><span class="st0">&#034;REMOTE_ADDR&#034;</span><span class="br0">&#093;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> strIpAddress;<br />
<span class="br0">&#125;</span></p>
<p>And here&#039;s the same IP retriever with proxy detection in .Net, but in VB.Net</p>
<p><span class="kw2">Public</span> <span class="kw6">Function</span> IpAddress<span class="br0">&#040;</span><span class="br0">&#041;</span><br />
&nbsp; &nbsp; <span class="kw6">Dim</span> strIpAddress <span class="kw2">As</span> <span class="kw2">String</span><br />
&nbsp; &nbsp; strIpAddress = Request.<span class="me1">ServerVariables</span><span class="br0">&#040;</span><span class="st0">&#034;HTTP_X_FORWARDED_FOR&#034;</span><span class="br0">&#041;</span><br />
&nbsp; &nbsp; <span class="kw6">If</span> strIpAddress = <span class="st0">&#034;&#034;</span> <span class="kw2">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;strIpAddress = Request.<span class="me1">ServerVariables</span><span class="br0">&#040;</span><span class="st0">&#034;REMOTE_ADDR&#034;</span><span class="br0">&#041;</span><br />
&nbsp; &nbsp; <span class="kw6">End</span> <span class="kw6">If</span><br />
&nbsp; &nbsp; IpAddress = strIpAddress<br />
<span class="kw6">End</span> <span class="kw6">Function</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/243-how-to-retrieve-a-visitors-ip-address-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPCart payment processor for Chase Paymentech (Orbital)</title>
		<link>http://www.doyourself.org/php/152-phpcart-payment-processor-for-chase-paymentech-orbital/</link>
		<comments>http://www.doyourself.org/php/152-phpcart-payment-processor-for-chase-paymentech-orbital/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 10:28:22 +0000</pubDate>
		<dc:creator>CarcaBot</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[(Orbital)]]></category>
		<category><![CDATA[Chase]]></category>
		<category><![CDATA[for]]></category>
		<category><![CDATA[payment]]></category>
		<category><![CDATA[Paymentech]]></category>
		<category><![CDATA[PHPCart]]></category>
		<category><![CDATA[processor]]></category>

		<guid isPermaLink="false">http://www.doyourself.org/?p=152</guid>
		<description><![CDATA[I was working on a project recently, implementing the PHPCart ecommerce shopping cart solution. The merchant uses Chase Paymentech as their credit card processor, and the PHPCart website mentioned that there was a gateway already made. However, I quickly found out that there wasn&#039;t so I had to code one myself! So I&#039;m offering it [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>I was working on a project recently, implementing the PHPCart ecommerce shopping cart solution. The merchant uses Chase Paymentech as their credit card processor, and the PHPCart website mentioned that there was a gateway already made. However, I quickly found out that there wasn&#039;t so I had to code one myself! So I&#039;m offering it up for free as open source. <span></span>Download the php <a href="http://www.justin-cook.com/wp/wp-content/uploads/2008/10/paymentechincphp.zip">chase payment gateway</a>.</p>
<p>You need to place it in the &#039;processor/&#039; directory of the PHPCart installation. It has the following features:</p>
<ul>
<li>Configure your merchant #</li>
<li>Configure your Terminal ID</li>
<li>Configure your BIN #</li>
<li>Specify the credit cards you accept (I suggest &#034;Visa,MasterCard,American Express,Discover,JCB&#034;)</li>
<li>Creates the proper expiry date with only the last two chars of the years from PHPcart</li>
<li>Chase processors dollar amount with implied decimal, so that&#039;s taken out</li>
<li>Converts the credit card name into the Chase approved format</li>
<li>You can uncomment line 39 and comment line 40 to switch to the testing server before you&#039;re certified.</li>
</ul>
<p>Anyhow, enjoy! If there are any enhancements or modifications you make, feel free to tell me about them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doyourself.org/php/152-phpcart-payment-processor-for-chase-paymentech-orbital/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
