<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>khalil qandil</title>
	<atom:link href="http://khl2007.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://khl2007.wordpress.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Mon, 03 Dec 2007 19:35:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='khl2007.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>khalil qandil</title>
		<link>http://khl2007.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://khl2007.wordpress.com/osd.xml" title="khalil qandil" />
	<atom:link rel='hub' href='http://khl2007.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Ajax and XML: Ajax for media</title>
		<link>http://khl2007.wordpress.com/2007/12/03/ajax-and-xml-ajax-for-media/</link>
		<comments>http://khl2007.wordpress.com/2007/12/03/ajax-and-xml-ajax-for-media/#comments</comments>
		<pubDate>Mon, 03 Dec 2007 19:33:14 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[1]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/12/03/ajax-and-xml-ajax-for-media/</guid>
		<description><![CDATA[Use Ajax techniques to show movies and slide shows &#160; &#160; &#60;!&#8211; &#160; &#160; &#160; &#8211;&#62; &#160; &#160; &#160; Level: Intermediate Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc. 23 Oct 2007 With the advent of widely available broadband, media, movies, images, and sound drive the Web 2.0 revolution. Learn to combine media [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=9&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr valign="top">
<td width="100%">
<h1><span style="color:#999999;"></span></h1>
<p><em>Use Ajax techniques to show movies and slide shows</em></p>
<p><img src="http://www.ibm.com/i/c.gif" class="display-img" height="6" width="1" /></td>
<td class="no-print" width="192"><a href="http://www.ibm.com/developerworks/"><br />
</a></td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr valign="top">
<td width="10"><img src="http://www.ibm.com/i/c.gif" height="1" width="10" /></td>
<td width="100%">
<table class="no-print" align="right" border="0" cellpadding="0" cellspacing="0" width="160">
<tr>
<td width="10"><img src="http://www.ibm.com/i/c.gif" height="1" width="10" /></td>
<td>
<table border="0" cellpadding="0" cellspacing="0" width="150">
<tr>
<td class="v14-header-1-small">&nbsp;</td>
</tr>
</table>
<table class="v14-gray-table-border" border="0" cellpadding="0" cellspacing="0" width="150">
<tr>
<td class="no-padding" width="150">&nbsp;</td>
</tr>
</table>
<p><!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- 11/28/07 refreshed by gem, per MOC -->   &lt;!&#8211;</p>
<table border="0" cellpadding="0" cellspacing="0" width="150">
<tr>
<td class="v14-header-2-small">&nbsp;</td>
</tr>
</table>
<table class="v14-gray-table-border" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="no-padding" width="150">
<table border="0" cellpadding="0" cellspacing="0" width="143">
<tr valign="top">
<td width="8"><img src="//www.ibm.com/i/c.gif" height="1" width="8" /></td>
<td>&nbsp;</td>
<td width="125">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
<p>&#8211;&gt;<!--END RESERVED FOR FUTURE USE INCLUDE FILES--></p>
<table border="0" cellpadding="0" cellspacing="0" width="150">
<tr>
<td class="v14-header-2-small">&nbsp;</td>
</tr>
</table>
<table class="v14-gray-table-border" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="no-padding" width="150">
<table border="0" cellpadding="0" cellspacing="0" width="143">
<tr valign="top">
<td width="8"><img src="http://www.ibm.com/i/c.gif" height="1" width="8" /></td>
<td>&nbsp;</td>
<td width="125">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>Level: Intermediate</p>
<p><a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#author">Jack D Herrington</a> (<a href="mailto:jherr@pobox.com?subject=Ajax%20for%20media&amp;cc=dwxed@us.ibm.com">jherr@pobox.com</a>), Senior Software Engineer, Leverage Software Inc.</p>
<p>23 Oct  2007</p>
<blockquote><p>With the advent of widely available broadband, media, movies, images, and 	sound drive the Web 2.0 revolution. Learn to combine media with technologies 	such as PHP and Asynchronous JavaScript™ + XML (Ajax) to create a compelling 	experience for your customers.</p></blockquote>
<p><!--START RESERVED FOR FUTURE USE INCLUDE FILES--> <!--END RESERVED FOR FUTURE USE INCLUDE FILES-->Ask people which site is most representative of the new wave of applications on the Web, 		and most will answer YouTube. It&#8217;s a site that has not only embraced new technology in 		a compelling way but changed how we view media and our relationship to it. Major 		stories can break on YouTube well before they appear on traditional media outlets, and 		when they don&#8217;t, YouTube acts like one big TiVo for the world.</p>
<p>Media sharing is changing the world, and from a technology standpoint, it&#8217;s not hard to 		do. This article shows how to put an Ajax front end on a simple Web video-hosting 		application.</p>
<p><a title="N10086" name="N10086"></a><span class="atitle">Simple video selection</span></p>
<p>I start with a Web site that holds a movie list and uses that list to select from 			one of several movies—a site on which you can change movies without 			actually moving from one page to another. <a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#list1">Listing 1</a> shows the code for the page.<br />
<a title="list1" name="list1"></a><strong>Listing 1. index.html</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;html&gt;
&lt;head&gt;
&lt;script src="prototype.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id="movieHost"&gt;
&lt;/div&gt;

&lt;div id="movieList"&gt;
&lt;/div&gt;

&lt;script&gt;
function setMovie( url )
{
  $('movieHost').innerHTML = '';
  var elEmbed = document.createElement( 'embed' );
  elEmbed.src = url;
  $('movieHost').appendChild( elEmbed );
}

new Ajax.Request( 'movies.xml', {
  method: 'get',
  onSuccess: function( transport ) {
    var movieTags = transport.responseXML.getElementsByTagName( 'movie' );

    $('movieList').innerHTML = '';

    var bFirst = true;
    for( var b = 0; b &lt; movieTags.length; b++ ) {
      var url = movieTags[b].getAttribute('url');
      var title = movieTags[b].getAttribute('title');
      if ( bFirst )
      {
        setMovie( url );
        bFirst = false;
      }
      var html = '&lt;a href="javascript:void setMovie(\''+url+'\');"&gt;';
      html += title+'&lt;/a&gt;&lt;br/&gt;';
      $('movieList').innerHTML += html;
    }
  }
} );
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
</td>
</tr>
</table>
<p>This page uses the excellent Prototype.js JavaScript library to make an Ajax request 			of the movies.xml data source. When the data is returned, the code finds all the 			movie tags using the <code>getElementsByTagName()</code> method. Then, 			for each movie tag, the code retrieves both the URL and the title. If the retrieved 			tag is for the first movie in the list, the script starts to play that movie right 			away. Otherwise, it adds an anchor tag, which acts as a movie selector to the 			<code>movieList &lt;div&gt;</code> tag.</p>
<p>This movie selector anchor calls the <code>setMovie()</code> function 			to start a particular movie. To start a movie, I simply set the contents of the 			<code>movieHost &lt;div&gt;</code> tag to empty, which removes any 			previous movie. Then, I set the contents to an <code>&lt;embed&gt;</code> 			tag whose URL is specified by the movie list.</p>
<p>The <code>&lt;embed&gt;</code> tag is the simplest way to get a movie 			onto a page, but it can have issues between browsers. Another option is to use both 			an <code>&lt;object&gt;</code> and an <code>&lt;embed&gt;</code> 			tag. (Yet another method is to use Macromedia Flash Player: I get into that a little 			<a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#flashmedia">later in the article</a>.)</p>
<p>In this simple example, the movies.xml file is just a flat file with some references 			to short home movies of mine. <a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#list2">Listing 2</a> shows the file.<br />
<a title="list2" name="list2"></a><strong>Listing 2. movies.xml</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;movies&gt;
  &lt;movie url="spider.mov" title="Spider" /&gt;
  &lt;movie url="swing.mov" title="Swing Set" /&gt;
  &lt;movie url="water.mov" title="Water Splash" /&gt;
&lt;/movies&gt;</pre>
</td>
</tr>
</table>
<p>When I navigate to the page, I see the something like <a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#fig1">Figure 1</a>.<br />
<a title="fig1" name="fig1"></a><strong>Figure 1. The simple movie list page</strong><br />
<img src="http://www.ibm.com/developerworks/library/x-ajaxxml7/index_400_304.jpg" alt="The simple movie list page" height="276" width="377" /><br />
The movie is at the top of the page, being played by the 			<code>&lt;embed&gt;</code> tag, and a list of available movies 			appears below it. If I click any of those links, the movie changes to the one 			I clicked.</p>
<p>Obviously, this system isn&#8217;t going to scale particularly well to large video 			repositories, so I need a way to do some searching on the movie list.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle">&nbsp;</td>
<td align="right" valign="top">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
<p><a title="N100FB" name="N100FB"></a><span class="atitle">Searchable movie lists</span></p>
<p>To add search functionality, I need to add a search box, which you can see in 			<a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#list3">Listing 3</a>. I&#8217;ve also added a search input field named 			<code>q</code>.<br />
<a title="list3" name="list3"></a><strong>Listing 3. Add search functionality</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;html&gt;
&lt;head&gt;
&lt;script src="prototype.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;table&gt;&lt;tr&gt;&lt;td valign="top"&gt;
  &lt;input type="text" id="q" onkeyup="search()"&gt;
  &lt;div id="movieList"&gt;
  &lt;/div&gt;
&lt;/td&gt;&lt;td valign="top"&gt;
  &lt;div id="movieHost"&gt;
  &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;script&gt;
function setMovie( url )
{
  $('movieHost').innerHTML = '';
  var elEmbed = document.createElement( 'embed' );
  elEmbed.src = url;
  $('movieHost').appendChild( elEmbed );
}

function search()
{
  new Ajax.Request( 'search.php?q='+escape($('q').value), {
    method: 'get',
    onSuccess: function( transport ) {
      var movieTags = transport.responseXML.getElementsByTagName( 'movie' );

      $('movieList').innerHTML = '';

      var bFirst = true;
      for( var b = 0; b &lt; movieTags.length; b++ ) {
        var url = movieTags[b].getAttribute('url');
        var title = movieTags[b].getAttribute('title');
        if ( bFirst )
        {
          setMovie( url );
          bFirst = false;
        }
        var html = '&lt;a href="javascript:void setMovie(\''+url+'\');"&gt;';
        html += title+'&lt;/a&gt;&lt;br/&gt;';
        $('movieList').innerHTML += html;
      }
    }
  } );
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
</td>
</tr>
</table>
<p>On the key-up event, I specified that the <code>search()</code> 			method should be called. That <code>search()</code> method is like 			the <code>Ajax.Request</code> call, with the exception that it now 			passes along the query string to a page called search.php. The search.php script 			returns the same XML format as the original, so the code that does the XML parsing 			doesn&#8217;t need to change.</p>
<p>I admit that a <code>search()</code> function on key-up is a bit too 			responsive for my taste. Ideally, the system would wait for a second or so before 			running the search so that I could finish a complete search text without having the 			list flicker in the meantime. You can easily implement such behavior by using the 			<code>window.setTimeout()</code> method.</p>
<p><a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#list4">Listing 4</a> shows the revised search.php script.<br />
<a title="list4" name="list4"></a><strong>Listing 4. search.php</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;?php
header( 'content-type: text/xml' );

$movies = array();
$movies['spider.mov'] = 'Spider';
$movies['swing.mov'] = 'Swing Set';
$movies['water.mov'] = 'Water Splash';
?&gt;
&lt;movies&gt;
&lt;?php
foreach( $movies as $k =&gt; $v ) {
if ( strlen( $_GET['q'] ) &gt; 0 &amp;&amp;
  preg_match( '/'.$_GET['q'].'/i', $v ) ) {
?&gt;
&lt;movie url="&lt;?php echo($k) ?&gt;" title="&lt;?php echo($v) ?&gt;" /&gt;
&lt;?php
} }
?&gt;
&lt;/movies&gt;</pre>
</td>
</tr>
</table>
<p>At the top of the script, I create an array that holds all the movies. For 			simplicity&#8217;s sake, I hard-coded the movies. But in reality, these elements are 			likely to come from a database of movie listings.</p>
<p>The code then iterates through the list and applies a regular expression of the 			search query to each movie title. When they match, a 			<code>&lt;movie&gt;</code> tag is output with the URL and the name.</p>
<p>When I start the page and type <code>s</code>, I get the page shown in 			<a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#fig2">Figure 2</a>.<br />
<a title="fig2" name="fig2"></a><strong>Figure 2. The movie query page with a 					simple query 				</strong><br />
<img src="http://www.ibm.com/developerworks/library/x-ajaxxml7/index2_1_400_299.jpg" alt="The movie query page with a simple query" height="275" width="375" /><br />
If I press Delete and type <code>water</code>, I get the page shown in 			<a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#fig3">Figure 3</a>.<br />
<a title="fig3" name="fig3"></a><strong>Figure 3. The movie query page looking 					for &#8220;water&#8221; movies 				</strong><br />
<img src="http://www.ibm.com/developerworks/library/x-ajaxxml7/index2_2_400_297.jpg" alt="The movie query page looking for       water movies" height="274" width="373" /><br />
While the point of this article is mainly to show how you could create a front end 			using Dynamic HTML (DHTML) and Ajax, there&#8217;s a lot more to creating a video sharing 			site.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0" width="2">
<tr>
<td valign="middle">&nbsp;</td>
<td align="right" valign="top">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
<p><a title="N1017F" name="N1017F"></a><span class="atitle">Video sharing basics</span></p>
<p>Jumping from the practical to the more theoretical for a moment, let me talk 				about how to handle some of the trickier video-sharing issues. There are three 				main issues to cover:</p>
<ul>
<li>How to store and stream the video</li>
<li>How to handle different video formats</li>
<li>How to get thumbnail images and video information from the uploaded 						files</li>
</ul>
<p>Video storage is a real problem—particularly for small applications. 				Video files are large, so expensive hardware is required to store them. And 				there are bandwidth charges for feeding them down the wire to your customers. 				You could buy your own equipment and put it in a hosting facility. Or you 				could use a service such as S3 from Amazon, which allows you to upload any 				material (database backups, images, movies, and so on) and feed them out of 				the Amazon datacenters for a reasonable cost. It&#8217;s probably worth looking 				into one of these services before bankrolling a datacenter roll-out.</p>
<p>The next issue—video formats—presents an interesting challenge. 				Many video formats exist, and not all players handle all formats. In fact, 				most players handle just their video format of choice. To make it easier on 				the customer, it&#8217;s probably best to standardize on a particular format, and 				then convert all the incoming video into that format. One particularly handy 				tool for doing that is a command-line application called <em>FFmpeg.</em> Not 				only can it convert from one video format to another, but it can also take 				frame snapshots and thus provide a thumbnail of the video before customers 				view it.</p>
<p><a title="flashmedia" name="flashmedia"></a>The choice of which video format to standardize on can be complex. Flash video 				is the clear winner at the moment, but Windows Media®, particularly with 				the release of Microsoft Silverlight (formerly WPF/Everywhere), is gaining 				ground. FFmpeg can export almost any movie to the Flash video format, which is 				compelling. And there are several free and open source Flash movie players that 				you can easily embed in your site. You can combine those players with the code 				above to make a complete end-to-end video-sharing solution with an Ajax front 				end.</p>
<p>But video isn&#8217;t the only thing going on with the Web: Image sharing is also 				important.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle">&nbsp;</td>
<td align="right" valign="top">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
<p><a title="N101AE" name="N101AE"></a><span class="atitle">Slide shows</span></p>
<p><a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#list5">Listing 5</a> shows a simple DHTML-based slide show that sources 			its data from an XML file.<br />
<a title="list5" name="list5"></a><strong>Listing 5. index.html</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;html&gt;
&lt;head&gt;
&lt;script src="prototype.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body bgcolor="black"&gt;
&lt;div style="text-align:center;"&gt;
&lt;img id="imgItem" src="" style="display:none;"&gt;&lt;br&gt;
&lt;div id="imgTitle" style="color:white;font-family:arial;font-size:24pt;"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
var g_images = [];
var g_slideIndex = 0;

function showSlide()
{
  $('imgTitle').hide();
  $('imgItem').hide();

  var height = 600;
  var width = ( height / g_images[ g_slideIndex ].height ) *
    g_images[ g_slideIndex ].width;

  $('imgItem').src = g_images[ g_slideIndex ].src;
  $('imgItem').width = width;
  $('imgItem').height = height;

  $('imgTitle').innerHTML = g_images[ g_slideIndex ].title;

  $('imgTitle').show();
  $('imgItem').show();

  g_slideIndex++;
  if ( g_slideIndex &gt;= g_images.length )
    g_slideIndex = 0;
}

new Ajax.Request( 'images.xml', {
  method: 'get',
  onSuccess: function( transport ) {
    var imageTags = transport.responseXML.getElementsByTagName( 'image' );

    for( var b = 0; b &lt; imageTags.length; b++ ) {
      g_images.push( {
        src: imageTags[b].getAttribute('src'),
        title: imageTags[b].getAttribute('title'),
        width: imageTags[b].getAttribute('width'),
        height: imageTags[b].getAttribute('height')
      } );
    }

    showSlide();

    window.setInterval( showSlide, 5000 );
  }
} );
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
</td>
</tr>
</table>
<table align="right" border="0" cellpadding="0" cellspacing="0" width="150">
<tr>
<td width="10"><img src="http://www.ibm.com/i/c.gif" height="1" width="10" /></td>
<td>
<table border="1" cellpadding="5" cellspacing="0" width="127">
<tr>
<td bgcolor="#eeeeee">one of ibm articles</td>
</tr>
</table>
</td>
</tr>
</table>
<p>The code is based on the Prototype.js JavaScript library. It uses the 			<code>Ajax.Request</code> object to get the list of images to show. 			The returned XML code is then parsed to get the URL as well as the width, height, 			and title of each image. The <code>showSlide()</code> function is 			then called to get the slide show ball rolling. A timer is set to go off every 			five seconds to move the show onto the next slide.</p>
<p>The slide show is implemented by having one <code>&lt;image&gt;</code> 			tag for the current image and one <code>&lt;div&gt;</code> tag for 			the title. The slide show simply hides the current image and title, sets the source 			of the image and the text of the title to the new slide contents, and then shows 			them. If you want something that fades in and out, I recommend using the 			<code>Effects</code> classes in the Scriptaculous library, which is 			built on Prototype.js.</p>
<p><a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#list6">Listing 6</a> shows the data images file.<br />
<a title="list6" name="list6"></a><strong>Listing 6. images.xml</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;images&gt;
 &lt;image src="images/megan1_875_700.jpg" title="Megan" width="875" height="700" /&gt;
 &lt;image src="images/oso1_875_700.jpg" title="Oso 1" width="875" height="700" /&gt;
 &lt;image src="images/oso2_873_700.jpg" title="Oso 2" width="873" height="700" /&gt;
&lt;/images&gt;</pre>
</td>
</tr>
</table>
<p>This one is hard-coded, but you can just as easily generate the XML code using 			a PHP script. The slide show is shown in progress in <a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#fig4">Figure 4</a>.<br />
<a title="fig4" name="fig4"></a><strong>Figure 4. The simple slide show</strong><br />
<img src="http://www.ibm.com/developerworks/library/x-ajaxxml7/slideshow_400_333.jpg" alt="The simple slide show" height="320" width="388" /><br />
<strong>Note:</strong> I previously published a much more elaborate version of the slide show 			(see <a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#resources">Resources</a> for a link). This one differs in that it 			uses the Prototype.js library and is much simpler in its transitions between 			slides.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle">&nbsp;</td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#main" class="fbox"><strong><br />
</strong></a></td>
</tr>
</table>
</td>
</tr>
</table>
<p><a title="N102BC" name="N102BC"></a><span class="atitle">Conclusion</span></p>
<p>Sites like Flikr and YouTube show just the tip of the full potential for media on 			the Web. This article provides some easy implementations of video and image 			browsing that you can use in your own project. If it works for you, please let me 			know by joining the developerWorks Ajax forum (see <a href="http://www.ibm.com/developerworks/library/x-ajaxxml7/index.html?S_TACT=105AGX44&amp;S_CMP=EDU#resources">Resources</a>) 			to talk about your success.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle">&nbsp;</td>
<td align="right" valign="top">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
<p><span class="atitle"><a title="download" name="download"></a>Download</span></p>
<table class="data-table-1" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<th scope="col">Description</th>
<th scope="col">Name</th>
<th scope="col">Size</th>
<th scope="col">Download method</th>
</tr>
<tr>
<th class="tb-row" scope="row">Sample code</th>
<td nowrap="nowrap">x-ajaxxml7-media.zip</td>
<td nowrap="nowrap">1090KB</td>
<td nowrap="nowrap"><a href="http://www.ibm.com/developerworks/views/download.jsp?contentid=259752&amp;filename=x-ajaxxml7-media.zip&amp;method=http&amp;locale=worldwide" class="fbox"><strong>HTTP</strong></a></td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td colspan="5"><img src="http://www.ibm.com/i/c.gif" border="0" height="12" width="12" /></td>
</tr>
<tr>
<td><img src="http://www.ibm.com/i/v14/icons/fw.gif" height="16" width="16" /></td>
<td><a href="http://www.ibm.com/developerworks/library/whichmethod.html" class="fbox">Information about download methods</a></td>
<td><img src="http://www.ibm.com/i/c.gif" height="1" width="50" /></td>
</tr>
</table>
<p><a title="author" name="author"></a><span class="atitle">About the author</span></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td colspan="3"><img src="http://www.ibm.com/i/c.gif" height="5" width="100%" /></td>
</tr>
</table>
</td>
</tr>
</table>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/9/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/9/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=9&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/12/03/ajax-and-xml-ajax-for-media/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/developerworks/library/x-ajaxxml7/index_400_304.jpg" medium="image">
			<media:title type="html">The simple movie list page</media:title>
		</media:content>

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/developerworks/library/x-ajaxxml7/index2_1_400_299.jpg" medium="image">
			<media:title type="html">The movie query page with a simple query</media:title>
		</media:content>

		<media:content url="http://www.ibm.com/developerworks/library/x-ajaxxml7/index2_2_400_297.jpg" medium="image">
			<media:title type="html">The movie query page looking for       water movies</media:title>
		</media:content>

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/developerworks/library/x-ajaxxml7/slideshow_400_333.jpg" medium="image">
			<media:title type="html">The simple slide show</media:title>
		</media:content>

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/icons/fw.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/c.gif" medium="image" />
	</item>
		<item>
		<title>Refine and debug PHP applications with syslog</title>
		<link>http://khl2007.wordpress.com/2007/11/02/refine-and-debug-php-applications-with-syslog/</link>
		<comments>http://khl2007.wordpress.com/2007/11/02/refine-and-debug-php-applications-with-syslog/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 20:20:14 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[php articles]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/11/02/refine-and-debug-php-applications-with-syslog/</guid>
		<description><![CDATA[PHP version of venerable UNIX syslog offers a simple, effective debugging tool An old technique for exploring a running program is to place code that &#8220;displays&#8221; the current value of variables at strategic points. But how is this done without interfering with the standard output of the program? With PHP&#8217;s syslog() facility, examining these values [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=8&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em>PHP version of venerable UNIX syslog offers a simple, effective debugging tool</em></p>
<blockquote><p>An old technique for exploring a running program is to place code that   &#8220;displays&#8221; the current value of variables  at strategic points. But how is this done   without interfering with the standard output  of the program? With PHP&#8217;s <code>syslog()</code>   facility, examining these values  is easy. Find out how.</p></blockquote>
<p><!--START RESERVED FOR FUTURE USE INCLUDE FILES--> &lt;!&#8211; if (document.referrer&amp;&amp;document.referrer!=&#8221;") {     // document.write(document.referrer);    var q = document.referrer;    var engine = q;    var isG = engine.search(/google\.com/i);    var searchTerms;    //var searchTermsForDisplay;    if (isG != -1) {  	   var i = q.search(/q=/); 	   var q2 = q.substring(i+2); 	   var j = q2.search(/&amp;/); 	   j = (j == -1)?q2.length:j; 	   searchTerms = q.substring(i+2,i+2+j); 	   if (searchTerms.length != 0) { 	       searchQuery(searchTerms); 	       document.write(&#8220;</p>
<div></div>
<p>&#8220;); 	   }    }  } //&#8211;&gt; <!--END RESERVED FOR FUTURE USE INCLUDE FILES-->Programming a computer is a tedious business, but it&#8217;s fun, too. One of the fun     aspects of programming is learning  about new ways to use an old tool. Recently, I was     contracted to fix a  dozen bugs in a large, complex, Linux®, Apache, MySQL, and     Linux, Apache, MySQL, PHP/Perl (LAMP)-based content-management system (CMS). The     architecture of the  CMS was the standard LAMP model, with Enterprise Red Hat Linux     running Apache V2.0. The code  that drove the Web sites consisted of a few hundred PHP     source modules  spread out over 30 subdirectories in the Apache document root     directory. The Apache and  MySQL portions of the system required no changes, so all my     bug-busting activities  were to occur in the PHP workspace.</p>
<p>After spending considerable time learning how the CMS worked, I grew to appreciate the   system&#8217;s elegant design and  I realized that, as in most mature programming   environments, this system relied on  only a small number of the available PHP functions.   (Shades of the old 80/20  rule here, where 80 percent of the work is accomplished with   20 percent of the available  functions.) This article shows how the process of debugging   an unknown but complex system  can help you learn about those little-used functions and   provides examples of how to  apply your new knowledge by using the rich functionality of   the <code>syslog()</code>  function.</p>
<p><a name="N10072"></a><span class="atitle">Under the microscope</span></p>
<p>With literally hundreds of functions available in the PHP programming language, some   (dare I say most?) functions are  never used unless you read about them in articles   like this one. Another way to learn more  about the language is to debug programs that   others have written in it. I&#8217;m  always impressed by the creative ways in which   programmers use the  tools.</p>
<p>Debugging, like computer programming, is part science and part art. When tracking down   obscure bugs in a  system that you didn&#8217;t create, you need to have a good feel for   where they manifest themselves  in the code. With hundreds of code modules to deal with,   a good place to begin is  where the output revealing the bug is found, then work your   way backward from there to  isolate the problem.</p>
<p>Say, for example, that a calculated value that was being output is known to be   incorrect. You must devise some  way to see the intermediary values that lead up to the   problem. Another problem  may manifest itself with bad data coming from an important   database query. You need to be able to see the SQL statement generated (and submitted by   the code to the  MySQL engine) to see whether that&#8217;s where the problem lies.</p>
<p>One age-old technique for doing this is to insert code that simply prints these strings   and values. Unfortunately, with a tool like PHP, or any Web-based application, you don&#8217;t   want to clutter up the natural output of  systems like this (that is, HTML code being   sent to the browser) with  debugging information, especially if the system you&#8217;re   examining is a  production server.</p>
<p>You could create a custom logging file and write log messages to it, but why not use   the tools that have already  been provided for you? Always remember: Don&#8217;t bury your   tools. The time spent seeing  whether the language authors have already provided a   library routine or  function to do something you suspect would be a commonly needed   function is  well spent. In fact, anytime you suspect that something should obviously be   part of a programming  package, it probably is.</p>
<p>I realized that what I needed to use was something similar to the syslog functionality   of UNIX®. I thought it  likely that PHP would have a hook into the syslog   functionality, so upon a quick review of the  PHP documentation, I found it! The PHP   <code>syslog()</code> function is  one that I had overlooked for many   years until I was contracted to  do this project. With <code>syslog()</code>, I was able to hunt down and exterminate  most of the bugs   in the production system  without introducing side effects other than the minute amount   of time it took for each  function to execute.</p>
<p>As you grow in your knowledge and become more skilled in your craft, different ways of   doing things become  apparent, and some way will eventually become the obvious way to   perform the required  task. What you must always keep in mind is that what is   obvious to you is not  obvious to other people. What may be simple to you can present a   mountain of  complexity to others.</p>
<p>Using a tool like the <code>syslog()</code> function keeps complexity   under control and provides  the added benefit of allowing easy customizations through   configuration files, such as  syslog.conf. For example, you can insert code to format a   SQL statement, log it to  <code>syslog()</code>, and pass it to MySQL for   execution. Later, a slight  modification of the syslog.conf file sends the text to   a different log file or  perhaps just to the bit bucket. Weeks or months later, if it   becomes necessary to see  what&#8217;s happening again, another simple change to the   syslog.conf file will restore the functionality.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" /></td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/library/os-php-syslog/index.html#main" class="fbox"><strong>Back to top</strong></a></td>
</tr>
</table>
</td>
</tr>
</table>
<p><a name="N100A3"></a><span class="atitle">syslog</span></p>
<p>syslog has a rich and colorful history in the UNIX world. Originally developed as part   of the Sendmail project,  syslog had proven to be so useful that many other tools have   incorporated in its functionality, proving that the simplest ideas are   sometimes  the most powerful.</p>
<p>In a nutshell, syslog allows applications to write tagged messages to a common set of   system log files that can  reside where it&#8217;s convenient for the programmers and   network administrators to access.  This means, for example, you can configure syslog on   a Web server to log  system messages on a different server — one that is perhaps   a few layers deeper  behind the security firewalls and easier for the aforementioned   administrators to access.  But for my purposes, I just accept the default behavior of   files being written to the  /var/log directory.</p>
<p>The syslog mechanism is started at boot-up, and its initial behavior is defined by the   rules in the syslog.conf file.  These rules enable you to finely tune what can and   cannot be logged with the  mechanism — which, on a high-volume, hard-working   server can translate  to log files of a manageable size.</p>
<p>Each rule consists of two fields: <em>selector</em> and <em>action</em>. Basically, the   selector field selects what  facility will be logged (for example, kern, user, mail,   lpr) and what priority the facility  has. The priority field contains a keyword, such as   <em>debug, info, notice,</em> or <em>warning</em>. And the action field of a rule   defines what to do with messages of a  kind that match the selector field. The rules can   specify which file to log the  message to, what machine to send the logging message to,   what user to send the message to (in the form of console messages), etc.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" /></td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/library/os-php-syslog/index.html#main" class="fbox"><strong>Back to top</strong></a></td>
</tr>
</table>
</td>
</tr>
</table>
<p><a name="N100C6"></a><span class="atitle">Logging</span></p>
<p>Study the info and man pages associated with the syslog facility to learn how to   configure the system for your needs.  In my case, I needed to know what the value of   various PHP variables were at  different times while the production CMS system was   running. I also  needed to know when certain modules were started and ended, as well as   what various intermediate variable  values were. Before getting into specifics   about what to log, let&#8217;s  set up the basics for logging.</p>
<p>With your favorite editor, create the file shown in Listing 1, name it test.php and put   it where your Apache document  root is found (on my system, it&#8217;s /var/www).<br />
<a name="list1"></a><strong>Listing 1. test.php</strong></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;PHP Test Page&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;?php
	syslog(LOG_NOTICE, "{$_SERVER['REMOTE_ADDR']}: test.php - PHP Index page accessed.");
	echo '&lt;p&gt;PHP Test Page&lt;/p&gt;';
    ?&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
</td>
</tr>
</table>
<p>You should have PHP installed and configured, as well. If not, check <a href="http://www.ibm.com/developerworks/library/os-php-syslog/index.html#resources">Resources</a> for  links on how to do this. If you configured everything   properly, you should  see the following text in your browser when you access the page   with the URL  http://localhost/test.php:</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>PHP Test Page</pre>
</td>
</tr>
</table>
<p>Next, open an X terminal window and type the following command to see what was logged   to the  /var/log/messages file:</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>tail /var/log/messages</pre>
</td>
</tr>
</table>
<p>If all goes well, you should see a line like this one near the end of the listing:</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>Jul 23 14:43:42 localhost apache2: 127.0.0.1: test.php - PHP Index page accessed.</pre>
</td>
</tr>
</table>
<p>If you did, that&#8217;s great. You have now verified that all you need to do to begin   detailed debugging of the complex  system you&#8217;re working on.</p>
<p>I have found it a good practice to use <code>syslog()</code> for all the   PHP/MySQL calls so that  every time you interact with the Web site, you can see which   SQL queries are generated in  real time to build the page returned to you. A   handy way to make this  work is to open a spare X terminal window and use the <code>tail</code>  command with the <code>-f</code> option for   &#8220;live&#8221; viewing of the  messages log:</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="code-outline">
<pre>tail -f /var/log/messages</pre>
</td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" /></td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/library/os-php-syslog/index.html#main" class="fbox"><strong>Back to top</strong></a></td>
</tr>
</table>
</td>
</tr>
</table>
<p><a name="N10110"></a><span class="atitle">What to log</span></p>
<p>Now that you&#8217;ve verified that the logging works and that you can see the results of the   logging mechanism, here are a  few tips for shortening the process of learning a foreign   system as quickly as  possible using these tools.</p>
<p>It&#8217;s important to know what modules do what beyond what their documentation   may say. For this reason, I like to  include logging messages that mark the beginning   and end of the modules. In this way, you can play with the pages of the Web site,   keeping an eye on the spare X  terminal window running the <code>tail -f   /var/log/messages</code> command.  In this way, you see which modules execute and in what   order every time the browser  requests a new page.</p>
<p>I also like to log the boundaries between different programs being called   into action during the running of  the PHP code. Examples include when the MySQL calls   are made to query the databases  or when external programs are called to make formatting   changes to data  (Extensible Stylesheet Language Transformation (XSLT) engines, for   example). The very practice of  systematically inserting these checkpoints into each PHP   code module helps you get used  to the names and locations of the modules. When the code   sends you messages  you see in the spare X terminal while browsing various pages, you   get important feedback that  facilitates and enhances your knowledge of the system.</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" /></td>
</tr>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tr align="right">
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" /></td>
<td align="right" valign="top"><a href="http://www.ibm.com/developerworks/library/os-php-syslog/index.html#main" class="fbox"><strong>Back to top</strong></a></td>
</tr>
</table>
</td>
</tr>
</table>
<p><a name="N10124"></a><span class="atitle">Conclusion</span></p>
<p>The syslog facility is a powerful tool for debugging an application someone else wrote.   It allows you to watch which  modules are being executed, which SQL statements are   executing, and which variable values  change as you navigate the Web site. This helps   pinpoint the modules in which  you&#8217;re likely to find problems.</p>
<p><a name="resources"></a><span class="atitle">Resources</span></p>
<p><strong>Learn</strong></p>
<ul>
<li> Learn more about the <a href="http://us.php.net/manual/en/function.syslog.php">                     <code>syslog()</code>                 </a> function.</li>
<li> Discover the <a href="http://en.wikipedia.org/wiki/Syslog">history of syslog</a> on   Wikipedia.</li>
<li>                 <a href="http://www.php.net/">PHP.net</a> is the central resource for PHP developers.</li>
<li> Check out the &#8220;<a href="http://www.ibm.com/developerworks/library/os-php-read">Recommended PHP reading list</a>.&#8221;</li>
<li> Browse all the <a href="http://www.ibm.com/developerworks/views/opensource/libraryview.jsp?search_by=php">PHP content</a> on developerWorks.</li>
<li> Expand your PHP skills by checking out IBM developerWorks&#8217; <a href="http://www.ibm.com/developerworks/opensource/top-projects/php.html">PHP project resources</a>.</li>
<li> To listen to interesting interviews and discussions for software developers, check out <a href="http://www.ibm.com/developerworks/podcast/">developerWorks  podcasts</a>.</li>
<li>   Using a database with PHP? Check out the <a href="http://www-306.ibm.com/software/data/info/zendcore/">Zend Core for   IBM</a>, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.</li>
<li> Stay current with developerWorks&#8217; <a href="http://www.ibm.com/developerworks/offers/techbriefings/">Technical events and webcasts</a>.</li>
<li> Check out upcoming conferences, trade shows, webcasts, and other <a href="http://www.ibm.com/developerworks/views/opensource/events.jsp">Events</a> around the world that are of interest to IBM open source developers.</li>
<li> Visit the developerWorks <a href="http://www.ibm.com/developerworks/opensource">Open source zone</a> for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM&#8217;s products.</li>
<li> Watch and learn about IBM and open source technologies and product functions with the no-cost <a href="http://www.ibm.com/developerworks/offers/lp/demos/?S_TACT=105AGX44&amp;S_CMP=ART">developerWorks On demand demos</a>.</li>
</ul>
<p><strong>Get products and technologies</strong></p>
<ul>
<li> Innovate your next open source development project with <a href="http://www.ibm.com/developerworks/downloads/">IBM trial software</a>, available for download or on DVD.</li>
<li> Download <a href="http://www.ibm.com/developerworks/downloads/">IBM product evaluation versions</a>, and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.</li>
</ul>
<p><strong>Discuss</strong></p>
<ul>
<li> Participate in <a href="http://www.ibm.com/developerworks/blogs">developerWorks blogs</a> and get involved in the developerWorks community.</li>
<li> Participate in the developerWorks <a href="http://www.ibm.com/developerworks/forums/dw_forum.jsp?forum=992&amp;cat=51&amp;S_TACT=105AGX44&amp;S_CMP=ART">PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS)</a>.</li>
</ul>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/8/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/8/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/8/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=8&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/11/02/refine-and-debug-php-applications-with-syslog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/icons/u_bold.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/icons/u_bold.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/icons/u_bold.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/rules/blue_rule.gif" medium="image" />

		<media:content url="http://www.ibm.com/i/v14/icons/u_bold.gif" medium="image" />
	</item>
		<item>
		<title>PHP Web Site Generation using Ruby</title>
		<link>http://khl2007.wordpress.com/2007/11/02/php-web-site-generation-using-ruby/</link>
		<comments>http://khl2007.wordpress.com/2007/11/02/php-web-site-generation-using-ruby/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 19:41:13 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[php articles]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/11/02/php-web-site-generation-using-ruby/</guid>
		<description><![CDATA[by Eric Rollins ntroduction &#8220;Raising the level of abstraction means moving toward WHAT, not HOW &#8211; telling the system what we want to do, declaratively,instead of how to do it, procedurally. This trend is desirable because declarative means the system does the work, while procedural means the user does the work.&#8221; C.J. Date, What Not [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=7&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><span class="wikitext"></span></p>
<h2>by Eric Rollins</h2>
<p><span class="wikitext"></p>
<h3>ntroduction</h3>
<blockquote><p><em>&#8220;Raising the level of abstraction means moving toward <strong>WHAT</strong>, not <strong>HOW</strong> &#8211; telling the system what we want to do, </em>declaratively<em>,instead of how to do it, </em>procedurally<em>.  This trend is desirable because declarative means the system does the work, while procedural means the user does the work.&#8221;</em> C.J. Date, <strong>What Not How</strong>, 2000.</p></blockquote>
<p>In Chapter 10 <em>Database Access</em> of <a href="http://www.codegeneration.net/cgia/" target="_new">Code Generation in Action</a> Jack Herrington and I presented a code generator written in <a href="http://www.ruby-lang.org/en/" target="_new">Ruby</a> that generated a SQL schema and Enterprise Java Beans database access tier based on an input XML schema description. For this article I have modified the Ruby code to generate <a href="http://www.php.net/" target="_new">PHP</a> code, and extended it to generate production PHP/HTML web pages.</p>
<p>I will cover building a database access layer for PHP, but I will also focus on the numerous benefits of generating production web pages using a system that has complete knowledge of the database schema. To finish I will discuss the highly productive development style that is enabled by continuously extending the declarative grammar in your own generator, and then provide some conclusions.</p>
<p>The Ruby source code and other files are available <a href="http://www.codegeneration.net/cgia/downloads/pgen_11.tgz" target="_new">here</a>.</p>
<p>I will not be explaining the Ruby source code; a detailed explanation is presented in Chapter 10 of the book.</p>
<p>And code generation provides many other advantages I do not discuss, please see the book and the <a href="http://www.codegeneration.net/" target="_new">Code Generation Network</a> website <a href="http://www.codegeneration.net/tiki-index.php?page=FrequentlyAskedQuestions" target="_new">FAQ</a> for more.</p>
<h3>Test Case</h3>
<p>Our test case is an application that manages book publishing.  It consists of 5 tables:</p>
<p><strong>Book</strong></p>
<table border="1">
<tr>
<td><strong>bookID</strong></td>
<td><strong>title</strong></td>
<td><strong>ISBN</strong></td>
<td><strong>authorID</strong></td>
<td><strong>publisherID</strong></td>
<td><strong>status</strong></td>
<td><strong>numCopies</strong></td>
</tr>
<tr>
<td>100</td>
<td>Object Oriented Perl</td>
<td>1-884777-79-1</td>
<td>100</td>
<td>100</td>
<td>2</td>
<td>1</td>
</tr>
<tr>
<td>101</td>
<td>Bitter Java</td>
<td>1-930110-43-X</td>
<td>101</td>
<td>100</td>
<td>2</td>
<td>1</td>
</tr>
</table>
<p><strong>Author</strong></p>
<table border="1">
<tr>
<td><strong>authorID</strong></td>
<td><strong>name</strong></td>
<td><strong>penName</strong></td>
</tr>
<tr>
<td>100</td>
<td>Conway</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>101</td>
<td>Tate</td>
<td>&nbsp;</td>
</tr>
</table>
<p><strong>Publisher</strong></p>
<table border="1">
<tr>
<td><strong>publisherID</strong></td>
<td><strong>name</strong></td>
</tr>
<tr>
<td>100</td>
<td>Manning</td>
</tr>
</table>
<p><strong>Store</strong></p>
<table border="1">
<tr>
<td><strong>storeID</strong></td>
<td><strong>name</strong></td>
</tr>
<tr>
<td>100</td>
<td>Borders</td>
</tr>
</table>
<p><strong>StoreBook</strong></p>
<table border="1">
<tr>
<td><strong>storeID</strong></td>
<td><strong>bookID</strong></td>
<td><strong>quantity</strong></td>
</tr>
<tr>
<td>100</td>
<td>100</td>
<td>45</td>
</tr>
<tr>
<td>100</td>
<td>101</td>
<td>399</td>
</tr>
</table>
<h3>Generator Architecture</h3>
<p>Our generator will take four XML files as input and using a series of templates will build a series of SQL and PHP files. The diagram below shows this relationship:</p>
<p><img src="http://www.codegeneration.net/articles/pgen/gen_stack.jpg" /></p>
<p>The four input files are:</p>
<table border="0">
<tr>
<td valign="top"><span class="wikitext"><strong><a href="http://www.codegeneration.net/articles/pgen/schema.xml.html" target="_new">schema.xml</a></strong></span></td>
<td><span class="wikitext">Describes the database tables, columns, column datatypes, andforeign key relationships.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong><a href="http://www.codegeneration.net/articles/pgen/extensions.xml.html" target="_new">extensions.xml</a></strong></span></td>
<td><span class="wikitext">Describes extended Value Objects, queries, and methods beyond those automatically generated from schema.xml.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong><a href="http://www.codegeneration.net/articles/pgen/pages.xml.html" target="_new">pages.xml</a></strong></span></td>
<td><span class="wikitext">Describes production list, add, update, and delete web pages which access tables described in schema.xml.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong><a href="http://www.codegeneration.net/articles/pgen/samples.xml.html" target="_new">samples.xml</a></strong></span></td>
<td><span class="wikitext">Describes sample data that is placed in a <em>Tests.php</em> web page to be automatically loaded via the generated PHP APIs.</span></td>
</tr>
</table>
<p>The output files are:</p>
<table border="0">
<tr>
<td valign="top"><span class="wikitext"><strong>tables.sql</strong></span></td>
<td><span class="wikitext">SQL script that creates tables and foreign key relationships.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong>code/*SS.php</strong></span></td>
<td><span class="wikitext">Database access layer (class) for table *; provides add, update, delete, get, getAll, and custom queries and methods.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong>code/*Value.php</strong></span></td>
<td><span class="wikitext">Value Object class for table *; used to pass data between web pages and *SS layer.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong>tests/Tests.php</strong></span></td>
<td><span class="wikitext">PHP web page used to load sample data described in <em>samples.xml</em>. </span></td>
</tr>
<tr>
<td valign="top"><strong><span class="wikitext">webtest/*Add.php, *Update.php, *Delete.php, ValueList.php</span></strong></td>
<td valign="top"><span class="wikitext">Test PHP web pages automatically generated for table *.</span></td>
</tr>
<tr>
<td valign="top"><span class="wikitext"><strong>web/*.php</strong></span></td>
<td><span class="wikitext">Production PHP web pages specified in <em>pages.xml</em>.</span></td>
</tr>
</table>
<h3>Database Access Architecture</h3>
<p>The PHP web pages do not access the database directly. Instead they pass Value Objects to the SS layer, which in turn calls the PHP PEAR DB database abstraction layer API. This is diagrammed below:</p>
<p><img src="http://www.codegeneration.net/articles/pgen/usage.jpg" /></p>
<p>The web browser talks to the PHP page on the Apache web server. The web page creates (or requests) a Value Object. The Value Object is passed to the SS layer, where it is transformed into a SQL statement passed to the PEAR database abstraction layer API, and on to the database.</p>
<h3>PHP Generator</h3>
<p>Now that we have completed a high level overview, lets drill into the generator itself. We first start with the lowest level, the schema.</p>
<h4>Schema</h4>
<p>The fundamental input to the generator is the <a href="http://www.codegeneration.net/articles/pgen/schema.xml.html" target="_new">schema.xml</a> file.  A fragment is show below:</p>
<pre>  &lt;table name="Book"&gt;</pre>
<pre>    &lt;column name="bookID" datatype="integer" not-null="true"</pre>
<pre>      primary-key="true" /&gt;</pre>
<pre>    &lt;column name="title" datatype="varchar" length="80" not-null="true" /&gt;</pre>
<pre>    &lt;column name="ISBN" datatype="varchar" length="80" not-null="true"</pre>
<pre>      unique="true" /&gt;</pre>
<pre>    &lt;column name="authorID" datatype="integer" not-null="true" /&gt;</pre>
<pre>    &lt;column name="publisherID" datatype="integer" not-null="true" /&gt;</pre>
<pre>    &lt;column name="status" datatype="integer" not-null="true" /&gt;</pre>
<pre>    &lt;column name="numCopies" datatype="integer" not-null="true" /&gt;</pre>
<pre>  &lt;/table&gt;</pre>
<pre>  &lt;foreign-key&gt;</pre>
<pre>    &lt;fk-table&gt;Book&lt;/fk-table&gt;</pre>
<pre>    &lt;fk-column&gt;authorID&lt;/fk-column&gt;</pre>
<pre>    &lt;fk-references&gt;Author&lt;/fk-references&gt;</pre>
<pre>  &lt;/foreign-key&gt;</pre>
<pre>  &lt;foreign-key&gt;</pre>
<pre>    &lt;fk-table&gt;Book&lt;/fk-table&gt;</pre>
<pre>    &lt;fk-column&gt;publisherID&lt;/fk-column&gt;</pre>
<pre>    &lt;fk-references&gt;Publisher&lt;/fk-references&gt;</pre>
<pre>  &lt;/foreign-key&gt;</pre>
<p>The schema.xml file specifies the database tables, columns, column datatypes, etc. It also specifies the foreign key relationships between tables. It is initially used to generate the database SQL schema file. The corresponding generated fragment is:</p>
<pre>  create table Book (</pre>
<pre>    bookID integer not null</pre>
<pre>    ,title varchar(80) not null</pre>
<pre>    ,ISBN varchar(80) not null unique</pre>
<pre>    ,authorID integer not null</pre>
<pre>    ,publisherID integer not null</pre>
<pre>    ,status integer not null</pre>
<pre>    ,numCopies integer not null</pre>
<pre>    ,constraint Book_pk primary key(bookID)</pre>
<pre>  );</pre>
<pre>  alter table Book</pre>
<pre>    add constraint Book_authorID</pre>
<pre>    foreign key (authorID)</pre>
<pre>    references Author (authorID);</pre>
<pre>  alter table Book</pre>
<pre>    add constraint Book_publisherID</pre>
<pre>    foreign key (publisherID)</pre>
<pre>    references Publisher (publisherID);</pre>
<p>In this example all table columns are listed directly in schema.xml.</p>
<h4>Stereotypes</h4>
<p>Unlike the generated SQL file, the schema.xml file does not need to directly list all the fields, datatypes, etc. of a table. In production systems many tables contain repetitive columns for purposes of audit trail, optimistic locking, etc. Instead of manually adding these fields to each table a <em>stereotype</em> may be used. This concept has been borrowed from UML, where it is represented in class diagrams as &lt;&lt;stereotype_name&gt;&gt;. Here we take advantage of our extensible XML grammar to attribute tables with desired stereotypes. An example would be to mark tables as &lt;constant/&gt; or &lt;dynamic/&gt;.</p>
<p>Dynamic tables would automatically have columns <em>create_date</em>, <em>modification_date</em>, and <em>modification_count</em>, used in optimistic locking, added. Database SQL trigger code to maintain these fields can be generated. Higher-level layers of generated code would automatically utilize these locking columns transparent to the developer.</p>
<p>Constant tables can produce generation-time or run-time warnings if they are modified. Later the &lt;dynamic/&gt; semantics could be extended to track column usage by adding <em>created_by</em> and <em>modified_by</em> columns, again automatically maintained by the higher layer code and again transparent to the developer.</p>
<p>The leverage provided by applying arbitrarily complex semantics to simple extensions to the grammar is a key advantage of this generation system. The equivalent in a UML-based generation system would be to apply a new custom stereotype &lt;&lt;dynamic&gt;&gt; to a class and extend the generator to implement the semantics.</p>
<p>Stereotypes leave the application developer free to concentrate on the important elements of the data design.</p>
<h4>Basic SS Layer and Value Objects</h4>
<p>The SS database access layer separates web pages from PEAR database access routines. The web pages communicate with the database by passing <em>Value</em> Objects. The SS layer is implemented as a separate PHP class wrapping each schema table. Default methods on the class accept or return Value Objects to add, update, delete, get, and getAll database rows. Independent of any customization a basic Value Object and SS layer is generated for each table in schema.xml.</p>
<p>The basic Value Object looks like this:</p>
<pre>  class BookValue {</pre>
<pre>    // private member variables</pre>
<pre>    var $_bookID;</pre>
<pre>    var $_title;</pre>
<pre>    var $_ISBN;</pre>
<pre>    var $_authorID;</pre>
<pre>    var $_publisherID;</pre>
<pre>    var $_status;</pre>
<pre>    var $_numCopies;</pre>
<pre>    // empty constructor</pre>
<pre>    function BookValue(){</pre>
<pre>      ...</pre>
<pre>    }</pre>
<pre>    // ResultSet constructor</pre>
<pre>    function setFromRow($row){</pre>
<pre>      ...</pre>
<pre>    }</pre>
<pre>  // member variable getters and setters</pre>
<pre>  function getBookID() { return $this-&gt;_bookID; }</pre>
<pre>  function setBookID($bookID){ $this-&gt;_bookID = $bookID; }</pre>
<pre>    ...</pre>
<pre>  }</pre>
<p>When you add or edit a record you need to construct or fetch a Value Object, then alter its contents and send it to the SS layer to be stored in the database.</p>
<p>The standard SS layer API looks like this:</p>
<pre>  class BookSS {</pre>
<pre>    function getBookValue($bookID)</pre>
<pre>    // returns array of BookValue</pre>
<pre>    function getAllBookValue($orderBy)</pre>
<pre>    function add($value)</pre>
<pre>    function update($value)</pre>
<pre>    function delete($bookID)</pre>
<pre>  }</pre>
<h4>Extending the API</h4>
<p>From schema.xml we create the SS layer and basic set of Value Objects. Production web pages often require more complex queries and Value Objects. Our generation system allows the Value Object, which defines the fields available for display, to be varied independently from the &#8220;where&#8221; portion of the custom query. A custom query can be used to return an auto-generated default Value Object, and an auto-generated get or getAll can be applied to a custom Value Object. Having them defined separately allows a custom Value Object to be defined once and then reused with many different queries. This is useful for the large number of web pages where the displayed table columns are identical but the specific query is different.</p>
<p>The <a href="http://www.codegeneration.net/articles/pgen/extensions.xml.html" target="_new">extensions.xml</a> file is used to define new Value Objects and add custom queries and methods to the SS layer.</p>
<p>Here are some extensions added to the Book table:</p>
<pre>  &lt;value-object name="BookWithNamesValue" base-table="Book"&gt;</pre>
<pre>    &lt;add-column table="Author" column-name="name" /&gt;</pre>
<pre>    &lt;add-column table="Author" column-name="penName" /&gt;</pre>
<pre>    &lt;add-column table="Publisher" column-name="name" /&gt;</pre>
<pre>  &lt;/value-object&gt;</pre>
<p>This defines a new Value Object. It will contain all the columns of the base table plus the new columns added from the other tables. Generated SQL strings will automatically perform the joins necessary to pull in the other columns. get* and getAll* methods are generated for this new Value Object.</p>
<pre>  &lt;sql-query-method name="getAllByTitle" value-object="BookWithNamesValue" &gt;</pre>
<pre>    &lt;parameter name="title" /&gt;</pre>
<pre>    &lt;where&gt;Book1.title = ?&lt;/where&gt;</pre>
<pre>  &lt;/sql-query-method&gt;</pre>
<p>This defines a new SQL query. It returns the previously defined new Value Object, and restricts its results using the specified SQL where-clause fragment.</p>
<pre>  &lt;custom-method name="updateStatusByPublisher" table="Book" return-type="void"&gt;</pre>
<p>This defines a custom method.  The actual implementation is placed in a hand-written PHP file, and is invoked by the SS layer.</p>
<h4>Pages</h4>
<p>The generator automatically produces test add, update, delete, and list web pages for all defined Value Objects, queries, and methods. Production web pages are specified in <a href="http://www.codegeneration.net/articles/pgen/pages.xml.html" target="_new">pages.xml</a>.  Supported page types are also <em>add, update, delete</em>, and <em>list</em>.</p>
<p>Here is an example list page for the Book table:</p>
<pre>  &lt;page name="BookList" type="list" label="Book List"</pre>
<pre>      value-object="BookWithNamesValue" order="Book1.title"&gt;</pre>
<pre>    &lt;buttons&gt;</pre>
<pre>      &lt;button label="Add Book" target="BookAdd"/&gt;</pre>
<pre>      &lt;button label="List Books in Stores" target="StoreBookList"/&gt;</pre>
<pre>    &lt;/buttons&gt;</pre>
<pre>    &lt;fields&gt;</pre>
<pre>      &lt;field name="update" label="Update" link="BookUpdate" virtual="true"/&gt;</pre>
<pre>      &lt;field name="delete" label="Delete" link="BookDelete" virtual="true"/&gt;</pre>
<pre>      &lt;field name="title" label="Title" link="BookView"/&gt;</pre>
<pre>      &lt;field name="ISBN" /&gt;</pre>
<pre>      &lt;field name="author_Name" label="Author Name"/&gt;</pre>
<pre>      &lt;field name="publisher_Name" label="Publisher Name"/&gt;</pre>
<pre>    &lt;/fields&gt;</pre>
<pre>  &lt;/page&gt;</pre>
<p>Here is how the generated web page looks in the browser:</p>
<p><img src="http://www.codegeneration.net/articles/pgen/book_list.jpg" /></p>
<p>Note this page is using the <em>BookWithNamesValue</em> Value Object defined in extensions.xml.  It automatically uses the SS method <em>getAllBookWithNamesValue()</em> (an extension is to use an alternate query method with the parameters read from the request).</p>
<p>The results are ordered by Book.title. The fields refer to the columns by name, or by table_Name in the case of columns added to the Value Object. Labels for all fields default to the column name but can be customized. Here customizations are specified directly; alternately they could be keys into a localization file indexed by user locale.</p>
<p>Hyperlinked buttons are supported both in the body of the table as well as separately. Different styles of hyperlinks (using icons, etc.) are one example of a feature easily added to the generator grammar based on page developer requests.</p>
<p>Here is the xml for an add page for the Book table:</p>
<pre>  &lt;page name="BookAdd" type="add" label ="Add Book"</pre>
<pre>     value-object="BookValue" success="BookList"&gt;</pre>
<pre>    &lt;fields&gt;</pre>
<pre>      &lt;field name="title" label="Title"/&gt;</pre>
<pre>      &lt;field name="ISBN" /&gt;</pre>
<pre>      &lt;field name="authorID" label="Author"&gt;</pre>
<pre>        &lt;select table="Author" text="name" /&gt;</pre>
<pre>      &lt;/field&gt;</pre>
<pre>      &lt;field name="publisherID" label="Publisher"&gt;</pre>
<pre>        &lt;select table="Publisher" text="name" /&gt;</pre>
<pre>      &lt;/field&gt;</pre>
<pre>      &lt;field name="status" label="Status"/&gt;</pre>
<pre>      &lt;field name="numCopies" label="Number of Copies"/&gt;</pre>
<pre>    &lt;/fields&gt;</pre>
<pre>  &lt;/page&gt;</pre>
<p>Here is the generated page in the browser:</p>
<p><img src="http://www.codegeneration.net/articles/pgen/book_add.jpg" /></p>
<p>Note HTML select tags (drop-down-lists) can be specified in the XML simply by listing the desired table and field name. The relevant SQL queries are automatically invoked at run-time. Because the generator has basic schema information available, field validation can be performed automatically:</p>
<p><img src="http://www.codegeneration.net/articles/pgen/book_add_validation.jpg" /></p>
<p>Currently the system performs <em>required</em> (not null) and <em>integer</em> validation automatically.  Single-column <em>unique</em> validation can also easily be added.  Maximum text field widths are currently set from the schema.</p>
<p>Note the similarity between the pages.xml specification for a page and a functional specification. Both specify which fields are on a page in what order, which tables fields are taken from, which buttons are on the page, which pages they link to, and what labels are on the fields and buttons. This has several advantages:</p>
<ul>
<li> This system has removed all the grunt work from the translation of functional specification into code. The developers can spend their time concentrating on business analysis and back-end business logic implementation instead of HTML, PHP, javascript, field validation, etc.</li>
<li> The amount of clerical work in connecting the front-end to the back-end is reduced, so there is significantly less chance of an issue with improper field mappings.</li>
<li> The simple declarative syntax of pages.xml aids communication with non-developer stakeholders on the project.</li>
<li> Re-targeting the system to other platforms and technologies &#8211; WAP, JSP, Swing, etc. is simplified.</li>
</ul>
<p>The pages.xml specifications are so short because all the layout, etc. decisions have been moved elsewhere in the system. CSS (Cascading Style Sheets) allow the colors, fonts, etc. of HTML elements to be specified in a separate file. But basics of page layout currently need to remain in the HTML file.</p>
<p>By moving the high-level specification of a page to pages.xml the generator controls the placement of page elements. A simple change to the generator template file can alter the button layout, for instance:</p>
<p><img src="http://www.codegeneration.net/articles/pgen/book_list_vertical_buttons.jpg" /></p>
<p>Here we have altered the generator with a new layout style. The generator enforces the latest layout style standards so the page developers can concentrate on business functions.</p>
<p>While templating systems alone can accomplish some of these goals, templating combined with generation can create a much more powerful system. Generators can both utilize templating systems in their implementation of generated pages and utilize a templating pattern in XML specification of pages.</p>
<p>Pages in pages.xml can be parameterized and treated as sub-components of other pages. In this way a single page description can be varied and utilized in many different pages. Of course hierarchically composed pages can be constructed from a mixture of generated and hand-written subpages.</p>
<h3>Development Style</h3>
<p>Currently the generator presented here (and available for download) is a &#8220;toy&#8221; system. A significant amount of functionality would need to be added to complete a production web site. From my experience performing this extension is a feasible and productive method of developing a working system.</p>
<p>The amount and types of extensions necessary depend on the kind of web site being developed. The production web pages may be nearly suitable as-is for a simple administrative user interface. Customer-facing list pages will need paging mechanisms, editable fields, icons, localization, etc. Headers and footers providing logos, navigation menus (also generatable from a declarative description!), etc. should also be added. Mechanisms for attaching hand-written fragments of PHP code to generated pages will also be needed. These fragments use HTTP get/post and session state variables in preparing query parameters, calling business logic, and controlling navigation flow.</p>
<p>The grammar used in each of the XML files, and especially pages.xml, forms a unique, very high level, declarative language describing your specific application. As new requirements arise during iterative analysis and implementation the grammar is extended (new XML elements and attributes are added). The XML grammar remains concise because it is not trying to be a general-purpose language. The development team will typically be split between business analyst / page author / business logic developers and generator tool developers. The generator tool developers will continuously add new features based on analyst / page author requests. The generator and its grammar co-evolve with your understanding of your application domain. A release of the generator is <em>done</em> when the entire system is ready to ship.</p>
<p>And a big tip for team productivity, for both the analysts and the generator developer: maintain up-to-date DTDs (Document Type Definitions) or XML Schemas for your XML grammar. When anyone has a question about their XML input ask &#8220;does it validate?&#8221; While none of the Ruby XML APIs currently validate, it is simple to create a 15-line <a href="http://www.codegeneration.net/articles/pgen/validate.py.html" target="_new">Python script</a> and add it as a build target to your system.  DTDs <a href="http://www.codegeneration.net/articles/pgen/schema.dtd.html" target="_new">schema.dtd</a>, <a href="http://www.codegeneration.net/articles/pgen/extensions.dtd.html" target="_new">extensions.dtd</a>, <a href="http://www.codegeneration.net/articles/pgen/pages.dtd.html" target="_new">pages.dtd</a>, and <a href="http://www.codegeneration.net/articles/pgen/samples.dtd.html" target="_new">samples.dtd</a> have been included with the code. DTDs and XML Schemas allow you to declaratively specify your XML grammar and automatically validate input files against it using the XML parser. Otherwise you have to check for grammatical errors yourself procedurally inside your generator. DTDs and XML Schemas also provide exact documentation of your current grammar for the other developers.</p>
<h3>Conclusions</h3>
<p>There are many different ways to implement a code generator that generates complete application tiers. I have presented the advantages of a generator that has complete schema information and uses a custom-defined and continuously extended declarative XML grammar. Some advantages I have presented are:</p>
<ul>
<li> At the schema level:
<ul>
<li> The SQL table creation code and higher level PHP code come from the same source, so they are guaranteed to always be in sync.</li>
<li> New stereotypes can be used to extend large numbers of tables through simple declarative changes. The generator automatically adds associated functionality to all relevant layers of the system.</li>
</ul>
</li>
<li> At the database access level:
<ul>
<li> Reusable Value Objects and queries can be independently defined and assembled together.</li>
<li> Value Object (and associated query) definitions automatically track simple schema changes like column addition.</li>
</ul>
</li>
<li> At the web page level:
<ul>
<li> Field validation can automatically be done based on datatype information from the schema.</li>
<li> Select (drop down) lists can be simply specified.</li>
<li> New grammar specifying features like new hyperlink types can easily be added.</li>
<li> Many aspects of page layout may be modified without touching the input XML files.</li>
<li> New page types and ways of compositing pages together can continuously be added.</li>
<li> Page definitions resemble high-level functional specifications, easing the work of developers and aiding communications with other stakeholders.</li>
</ul>
</li>
</ul>
<p>Finally, all of these and many other discussed advantages are possible because we have built our generator around a declarative grammar that focuses on <strong>WHAT</strong>, not <strong>HOW</strong>.</p>
<p><em>Special thanks to <a href="http://www.codegeneration.net/tiki-index.php?page=AboutUs" target="_new"> Jack Herrington</a> for editorial suggestions.</em><br />
</span></p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/7/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/7/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/7/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=7&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/11/02/php-web-site-generation-using-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>

		<media:content url="http://www.codegeneration.net/articles/pgen/gen_stack.jpg" medium="image" />

		<media:content url="http://www.codegeneration.net/articles/pgen/usage.jpg" medium="image" />

		<media:content url="http://www.codegeneration.net/articles/pgen/book_list.jpg" medium="image" />

		<media:content url="http://www.codegeneration.net/articles/pgen/book_add.jpg" medium="image" />

		<media:content url="http://www.codegeneration.net/articles/pgen/book_add_validation.jpg" medium="image" />

		<media:content url="http://www.codegeneration.net/articles/pgen/book_list_vertical_buttons.jpg" medium="image" />
	</item>
		<item>
		<title>tranzlation in php</title>
		<link>http://khl2007.wordpress.com/2007/10/24/tranzlation-in-php/</link>
		<comments>http://khl2007.wordpress.com/2007/10/24/tranzlation-in-php/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 18:40:49 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[php articles]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/10/24/tranzlation-in-php/</guid>
		<description><![CDATA[Internationalization and localization of a web page is simply the act of setting it up to be able to handle displaying in multiple languages and adding those different languages in. There are many different ways in which to do this. One of the simplest is to just make sure that all your strings that you [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=6&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p class="articlePara"><strong> Internationalization and localization of a web page is simply the act of setting it up to be able to handle displaying in multiple languages and adding those different languages in. There are many different ways in which to do this. One of the simplest is to just make sure that all your strings that you ever output are stored as variables or constants in an included file. That way, you can make multiple copies of that file,each with different language versions written into them. Just include the appropriate file for the language that you want to display.</strong></p>
<p class="articlePara"><strong> This idea can be extended to images as well because any image with text on it would also need translated. Just define the <code>imgsrc</code> of each image in your included file as well.</strong></p>
<p class="articlePara"><strong> Listings 9.7.1, 9.7.2, and 9.7.3 are examples of what these included files could look like, given in three different languages.</strong></p>
<p class="articleHeader"><strong>Listing 9.7.1 Localization File for English—Filename: en.php</strong></p>
<p class="example" style="width:395px;">
<pre><strong>&lt;?php
// Declare all text strings that we need,
// in English.
$GLOBALS['text'] = array (
  'welcome' =&gt; 'Welcome to our website!',
  'thanks' =&gt; 'Thank you for your patronage.',
  'sky' =&gt; 'The sky is falling!',
  'game' =&gt; 'Would you like to play a game?',
  'switch' =&gt; 'Switch the language to:',
  );

// Now, also define alternative imgs for our use
$GLOBALS['imgsrc'] = array (
  'title' =&gt; 'graphics/title.en.png',
  'footer' =&gt; 'graphics/foot.en.jpg'
  );
?&gt;
</strong></pre>
<p class="articleHeader"><strong>Listing 9.7.2 Localization File for French—Filename: fr.php</strong></p>
<p class="example" style="width:395px;">
<pre><strong>&lt;?php
// Declare all text strings that we need,
// in French.
$GLOBALS['text'] = array (
  'welcome' =&gt; 'Bienvenue à
     notre site Web!',
  'thanks' =&gt; 'Merci de soutenir nos affaires.',
  'sky' =&gt; 'Le ciel tombe!',
  'game' =&gt; 'Aimez-vous jouer un jeu?',
  'switch' =&gt; 'Commutez la langue à:',
  );

// Now, also define alternative imgs for our use
$GLOBALS['imgsrc'] = array (
  'title' =&gt; 'graphics/title.fr.png',
  'footer' =&gt; 'graphics/foot.fr.jpg'
  );
?&gt;
</strong></pre>
<p class="articleHeader"><strong>Listing 9.7.3 Localization File for German—Filename: de.php</strong></p>
<p class="example" style="width:395px;">
<pre><strong>&lt;?php
// Declare all text strings that we need,
// in German.
$GLOBALS['text'] = array (
  'welcome' =&gt; 'Willkommen zu unserer
     Web site!',
  'thanks' =&gt; 'Danke für Ihr Patronat.',
  'sky' =&gt; 'Der Himmel fällt!',
  'game' =&gt; 'Wurden Sie mögen ein
     Spiel spielen?',
  'switch' =&gt; 'Schalten Sie die Sprache zu:',
  );

// Now, also define alternative imgs for our use
$GLOBALS['imgsrc'] = array (
  'title' =&gt; 'graphics/title.de.png',
  'footer' =&gt; 'graphics/foot.de.jpg'
  );
?&gt;
</strong></pre>
<p class="articlePara"><strong> Now that we have all the different language versions saved in separate files, we want to make it easy for any page to use these. Therefore, a library should be created to handle this. The library shown in Listing 9.7.4 when included in a web page automatically detects what language should be used based on a <code>GET</code> string or a cookie. It also provides a function for easily creating some XHTML that allows for switching languages.</strong></p>
<p class="articleHeader"><strong>Listing 9.7.4 Localization Library—Filename: language.php</strong></p>
<p class="example" style="width:395px;">
<pre><strong>&lt;?php
// This is a library, that by including it,
// automatically determines the proper language
// to use and includes the language file.

// First define an array of all possible
// languages:
$languages = array('en' =&gt; 'English',
  'fr' =&gt; 'French', 'de' =&gt; 'German');

// Look at the GET string to see if lang is
// specified:
  if (isset($_GET['lang'])) {
  // It's been specified, so set the language
  $lang = $_GET['lang'];
  // While here, send a cookie to remember this
  // selection for 1 year.
  setcookie('lang', $lang, time()+(3600*24*365));
}
// Ok, otherwise look for the cookie itself:
elseif (isset($_COOKIE['lang'])) {
  // Use this
  $lang = $_COOKIE['lang'];
} else {
  // Otherwise, default to English
  $lang = 'en';
}

// Make sure that the language string we have is
// a valid one:
if (!(in_array($lang, array_keys($languages)))) {
  die("ERROR: Bad Language String Provided!");
}

// Now include the appropriate language file:
require_once "{$lang}.php"

// As one last step, create a function
// that can be used to output language
// options to the user:
function switch_language_options() {
  // Include a few globals that we will need:
  global $text, $languages, $lang;

  // Start our string with a language specific
  // 'switch' statement:
  $retval = $text['switch'];

  // Loop through all possible languages to
  // create our options.
  $get = $_GET;
  foreach ($languages as $abbrv =&gt; $name) {
    // Create the link, ignoring the current one.
    if ($abbrv !== $lang) {
      // Recreate the GET string with
      // this language.
      $get['lang'] = $abbrv;
      $url = $_SERVER['PHP_SELF'] . '?' .
        http_build_query($get);
      $retval .= " &lt;a href=\"{$url}\"&gt;
        {$name}&lt;/a&gt;";
    }
  }

// Now return this string.
  return $retval;
}
?&gt;
</strong></pre>
<p class="articlePara"><strong> With this completed, it can be easy to generate a web page that is language independent, such as Listing 9.7.5.</strong></p>
<p class="articleHeader"><strong>Listing 9.7.5 Localization: Complete Example</strong></p>
<p class="example" style="width:395px;">
<pre><strong>&lt;?php
// Include our language library:
require_once 'language.php';
?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD
 XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;title&gt;&lt;?= $text['welcome'] ?&gt;&lt;/title&gt;
&lt;meta http-equiv="Content-Type"
  content="text/html; charset=iso-8859-1" /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;&lt;img alt="&lt;?= $text['welcome'] ?&gt;"
  src="&lt;?= $imgsrc['title'] ?&gt;"
height="50" width="500" /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;?= $text['thanks'] ?&gt;&lt;/h2&gt;
&lt;p&gt;&lt;?= $text['game'] ?&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="&lt;?= $text['sky'] ?&gt;"
  src="&lt;?= $imgsrc['footer'] ?&gt;"
height="10" width="220" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;?= switch_language_options(); ?&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</strong></pre>
<p class="articlePara"> <strong><strong>Note:</strong> PHP also provides an interface to the GNU <code>gettext</code><code>gettext</code><a href="http://php.net/gettext">http://php.net/gettext</a>.</strong> library. This is a generic library created to handle internationalization/localization problems. Using it requires building the support for it into PHP and installing the  library on your computer. If you want to learn more about this, visit</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/6/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/6/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/6/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=6&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/10/24/tranzlation-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>
	</item>
		<item>
		<title>google tricks</title>
		<link>http://khl2007.wordpress.com/2007/10/24/google-tricks/</link>
		<comments>http://khl2007.wordpress.com/2007/10/24/google-tricks/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 17:30:04 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[php articles]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/10/24/google-tricks/</guid>
		<description><![CDATA[Introduction Search engines are good. Google has been the indisputable king of search engines for quite some time now, and even if msn is trying it&#8217;s best to pursue the surfers with a new engine, a massive advertising budget and a new &#8220;css&#8221; based layout, google is still on top. Yahoo and Ask Jeeves has [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=5&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Search engines are good. Google has been the indisputable king of search engines for quite some time now, and even if <a href="http://www.msn.com/">msn</a> is trying it&#8217;s best to pursue the surfers with a new engine, a massive advertising budget and a new &#8220;css&#8221; based layout, google is still on top. <a href="http://www.yahoo.com/">Yahoo</a> and <a href="http://www.ask.com/">Ask Jeeves</a> has always been alternatives, and still are, while the 90&#8242;s big shots <a href="http://www.altavista.com/">AltaVista</a> and <a href="http://www.webcrawler.com/">webcrawler</a> has taken a big step down.</p>
<p>This article will demonstrate how you can build your own search engine using Google&#8217;s API service and some PHP magic. Google has released the source code for it&#8217;s results, and they are free for anyone to use with the only drawback being a limit of 1000 queries per day and displays a maximum of 10 results at a time.</p>
<p>And while we&#8217;re at it, we might as well do it right this time, using semantic XHTML markup and accessible forms. This will also make it possible for you to add your own search engine to your site with googles powerful back-end serving up the results.</p>
<p style="border-left:1px dotted #aaaaaa;float:right;margin:0 0 0 1em;padding:1em 0 1em 1em;"> <!-- google_ad_client = "pub-8483490087052587"; google_ad_width = 336; google_ad_height = 280; google_ad_format = "336x280_as"; google_ad_channel ="4868400459"; google_ad_type = "text"; google_color_border = "FFFFFF"; google_color_bg = "FFFFFF"; google_color_link = "006699"; google_color_url = "999988"; google_color_text = "555544"; //-->  </p>
<h3>The retro-cool google</h3>
<p>Google is loved by many and hated by few. It&#8217;s light, fast, (almost) ad-free and secure. But a quick look under the hood makes any web developer wonder why the biggest of them all are still using markup that belong to the 90&#8242;s. Inaccessible forms, tables for layout, markup errors, incorrect ampersands in the url, old-school <code>&lt;b&gt;</code> tags etc. etc. Now, in order to change all this you could write them an email explaining your concern about their coding. Or you could create your own search engine, built on the same reliable back-end but re-coded with modern front-end technologies. We will do the later in this article.</p>
<h3>Google API</h3>
<p>As mentioned before, google released their search results to the public some time ago. All you have to do is sign up a google account at <a href="https://www.google.com/accounts/NewAccount">https://www.google.com/accounts/NewAccount</a> if you don&#8217;t already have one. Once there, you can request for an API key. If you have problems obtaining one, see their help pages for more info. This key is exactly what is sounds like &#8211; a key to access their massive database of basically all web pages available on the world wide wisdom. We will use this key in the example, so make sure you have one before you continue.</p>
<h3>PHP and NuSOAP</h3>
<p>We will use <a href="http://www.php.net/">PHP</a> to create the program. PHP is an open-source server side scripting language and is very similar to perl and c++. Ask your host if they support it (all good hosts do) or try to install it on your local machine. Not only will we use PHP, but also an extension called NuSOAP. It contains many useful classes, especially for tasks like accessing the google results and parsing them. You can download the package at <a href="http://sourceforge.net/projects/nusoap/">http://sourceforge.net/projects/nusoap/</a>. Once downloaded, unzip the .zip archive and locate the folder named &#8220;lib&#8221;. In there you will find several PHP files with the extension &#8220;.php&#8221;. These are the files we will use to access the NuSOAP library.</p>
<h3>Getting Started</h3>
<p>To get started with the tutorial, make sure you go through these steps:</p>
<ol>
<li>Get an API key at <a href="https://www.google.com/accounts/NewAccount">https://www.google.com/accounts/NewAccount</a></li>
<li>Create a new directory in the root called &#8220;search&#8221;</li>
<li>Download the NuSOAP library at <a href="http://sourceforge.net/projects/nusoap/">http://sourceforge.net/projects/nusoap/</a></li>
<li>Unzip the NuSOAP .zip archive, locate the lib folder and copy all files in the folder into the search folder you just created</li>
<li>Read the next section</li>
</ol>
<h3>Google did wrong &#8211; let&#8217;s make it right</h3>
<p>Semantic markup and web standards are the way of the future. It&#8217;s like any tool or technological advance &#8211; first comes availability and then perfection. Google&#8217;s markup is quite far from perfection, but we know better. After a quick analyze of the search results page I decided that a definition list would probably be the best way to code the results, since it has all the typical fields: a title and descriptions. So this is basically what we want:</p>
<p><code> &lt;form&gt;<br />
&lt;p&gt;[search_form]&lt;/p&gt;<br />
&lt;/form&gt;<br />
&lt;p class="results"&gt;[results_info]&lt;/p&gt;<br />
&lt;dl&gt;<br />
&lt;dt&gt;&lt;a href="[url]"&gt;[title]&lt;/a&gt;&lt;/dt&gt;<br />
&lt;dd&gt;[description]&lt;/dd&gt;<br />
&lt;dd class="url"&gt;[url] - [size]&lt;/dd&gt;<br />
[ ... repeated ... ]<br />
&lt;/dl&gt;<br />
&lt;p class="nav"&gt;[page_nav]&lt;/p&gt;<br />
</code></p>
<h3>Getting the PHP stuff working</h3>
<p>Now is the time to <a href="http://www.stylegala.com/files/search/index.zip">download the index.php sample file</a>. This is the file that contains all vital php instructions to create the search engine. Once downloaded, upload it to the search folder on your root directory or open it up in your favourite text editor. Once there, lets take a look at the general sections of the PHP file:</p>
<ol>
<li>Preferences</li>
<li>Main program</li>
<li>Sub programs</li>
<li>XHTML rendering</li>
</ol>
<h3>1. Preferences</h3>
<p>Theese are the preferences. Modify as you wish, but never change the google API key once you obtained it.</p>
<ul class="txt">
<li><code>$pref-&gt;text</code> &#8211; defines what text should be displayed if google doesn&#8217;t find any text.</li>
<li><code>$pref-&gt;title</code> &#8211; defines what title should be displayed if google doesn&#8217;t find any title.</li>
<li><code>$pref-&gt;key</code> &#8211; this is where you should enter your Google API key &#8211; read previous section for more info on how to obtain one.</li>
<li><code>$pref-&gt;results</code> &#8211; sets the number of results to be displayed on one page. Google API has a limit of max 10 results.</li>
<li><code>$pref-&gt;start</code> &#8211; sets the starting item to be displayed. If set to &#8220;Auto&#8221;, a page navigation will appear in the bottom.</li>
<li><code>$pref-&gt;safe</code> &#8211; toggles the SafeSearch filter  on or off. &#8220;false&#8221; means off and &#8220;true&#8221; means on.</li>
<li><code>$pref-&gt;filter</code> &#8211; toggles the google filter for similar pages on the same domain on or off. &#8220;false&#8221; means off and &#8220;true&#8221; means on.</li>
</ul>
<h3>2. Main program</h3>
<p>The main program contain 4 commands:</p>
<ol>
<li><code>require_once('nusoap.php');</code></li>
<li><code>$query = $_GET['q'];</code></li>
<li><code>$results = getResults($query);</code></li>
<li><code>$title = getTitle($query);</code></li>
</ol>
<p>The first line includes the NuSOAP lib into the document. The second line collects the query string. The third collects the search results in a variable called $results and the fourth line collects the document title into $title.</p>
<h3>3. Sub programs</h3>
<p>I am not going into detail of all aspects of these functions, but here is a quick review. The <code>getTitle();</code> is very simple and collects the title depending on what and if the search query has been done. The <code>getResults();</code> parses the <code>$query</code> string and collects the google results using the NuSOAP functions, then returns the data. The markup is parsed with some regular expressions using the <code>preg_replace();</code> function in order to remove unwanted tags, correct ampersands and convert <code>&lt;b&gt;</code> tags to XHTML. The function also contains an advanced page and results calculator if you have set the <code>$pref-&gt;start</code> to &#8220;auto&#8221;.</p>
<h3>4. XHTML rendering</h3>
<p>The last section looks familiar for any web programmer. A few things should be noted here:</p>
<ol>
<li>The default style is my childish attempt to assimilate google&#8217;s well known layout interface. You can change this to whatever you like.</li>
<li>Please note the <code>&lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;</code> line. That means that the PHP will take care of the title.</li>
<li>The form also contains some PHP commands, leave them where they are or experiment as you wish.</li>
<li>The most important line is <code>&lt;?php echo $results; ?&gt;</code>. This is where the data comes in from the PHP program.</li>
</ol>
<h3>Wrapping it all up</h3>
<p>Once you have configured the preferences, just save your file and point your browser to http://www.yoursite.com/search/index.php and start googling. Or, you can have a look at our <a href="http://www.stylegala.com/files/search/index.php">example demo</a>. You can alter and refine the PHP code depending on what level you master, or you can stick to modifying the XHTML rendering in the fourth section of the document. In any way, you will have a fully standard compilant, valid and highly customizable google search engine at your disposal, ready to use at your site or wherever you like. Remember that the google API only allows 1000 queries per day, so if the search results are empty, you might need to cool off and take a walk.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=5&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/10/24/google-tricks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>
	</item>
		<item>
		<title>Creating a PHP-Based Content Management System</title>
		<link>http://khl2007.wordpress.com/2007/10/12/creating-a-php-based-content-management-system/</link>
		<comments>http://khl2007.wordpress.com/2007/10/12/creating-a-php-based-content-management-system/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 21:25:12 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[php articles]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[Creating a PHP-Based Content Management System]]></category>
		<category><![CDATA[khalilqandil]]></category>
		<category><![CDATA[learn php]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/10/12/creating-a-php-based-content-management-system/</guid>
		<description><![CDATA[part one i will ad the part tow in few days If you&#8217;re going to run an intranet site, then you&#8217;ll probably want a content management system (CMS) — a tool used to organize documents and keep track of what&#8217;s where. I&#8217;ve covered a plethora of such systems in previous articles, but for many businesses [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=4&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>part one</h2>
<p>i will ad the part tow in few days</p>
<p><strong>If</strong> you&#8217;re going to run an intranet site, then you&#8217;ll probably want a content management system (CMS) — a tool used to organize documents and keep track of what&#8217;s where. I&#8217;ve covered a plethora of such systems in previous articles, but for many businesses there can be only one solution: to design and implement their own custom system.</p>
<p>Why? It&#8217;s not like the off-the-shelf systems lack features or stability. On the contrary, many have been crafted by hundreds of man-hours of work, and are successfully implemented by thousands of Web sites and intranets. But when it comes down to it, it&#8217;s hard to have much clue as to how they work. If you want to customize the way these systems operate, you&#8217;ll often have to wade through vast amounts of (often badly documented) code to find what needs changing.</p>
<p>Writing your own CMS, on the other hand, can lead to a solution that is better suited to your requirements, better addresses the needs of your users, and is better understood by your development team. If you have the time and expertise to write your own in-house system, it may well prove the better option. And this is what I shall be embarking upon in this series.</p>
<p>The system we create will be written using the PHP programming language, which excels in the development of Web-based systems. I&#8217;ll be using MySQL as the database server, but the system will be written to allow the use of alternative databases, such as PostgreSQL or SQL Server.</p>
<p>So what will this system actually do? First and foremost, it will allow the bulk of the intranet or Internet site&#8217;s content to be easily stored and managed in a database. We&#8217;ll also include a number of other features required for running a successful site, such as authenticating users and managing files.</p>
<p>Some basic PHP knowledge will be needed for coding your own CMS, although most of what you&#8217;ll need to know will be demonstrated here. I&#8217;ll assume you have access to a server running PHP and a database system. Once the series is complete, I&#8217;ll make available a polished version of the CMS for anyone to use.</p>
<p>I don&#8217;t promise the vast array of abilities incorporated into systems such as Postnuke, Smarty, or some commercial content management systems. But just having lots of features isn&#8217;t always what&#8217;s needed, and this series will help you to develop a system specifically targeted to your needs. With that, let&#8217;s get going&#8230;</p>
<p><strong>Planning the CMS</strong></p>
<p>To begin with, we&#8217;ll plan how our PHP-based content management system will work. In subsequent articles, I&#8217;ll demonstrate how each of the major components are implemented, leading to a complete system.</p>
<p>The first step is a basic specification of what our CMS must do. Obviously, this will depend on your needs:</p>
<ul>
<li><strong>Content Management:</strong> Probably the most vital function of the system, it must store content such as documents and news in a database, and display to the user whatever he or she requests. An easy-to-use interface is required to allow editors to add, remove, or modify content.</li>
<li><strong>User authentication:</strong> There may be certain areas of the intranet or Internet site to which we wish to limit access. At the very least this will be the &#8220;admin&#8221; area, where the editor of the site will be able to add, edit or modify content. You may also wish to have areas only available to certain departments or staff.</li>
<li><strong>Page uniformity/templates:</strong> The system should have a uniform look and feel, and this design element needs to be separated from the logic element, e.g., the programming required to display an article should be separated from how that article looks (stylistically) on the screen.</li>
</ul>
<p><strong>Object-Oriented Programming</strong></p>
<p>PHP helps the design process by supporting object-oriented programming (OOP). When putting together our system, there are certain chunks of programming that are needed again and again, such as database access, user authentication, etc. To keep this code neat and tidy, we bundle it together in PHP files called &#8220;classes.&#8221; We can then create instances (or &#8220;objects&#8221;) of these classes whenever they are needed. Thus, the class can be thought of as a blueprint for one or more instances.</p>
<p>For example, we could create a class with code for connecting to a database, and then create an instance of that class whenever we need to query the database. If this isn&#8217;t immediately clear then don&#8217;t worry, it will become more obvious when we start coding. This method of programming allows a complex system to be broken down into smaller and simpler blocks, which makes life easier when it comes to management, modification, and error finding.</p>
<p>Let&#8217;s now consider how the system will fit together. This will doubtless be tweaked as you consider the requirements for your own system, but below is a basic outline:</p>
<p align="center"> <img src="http://www.intranetjournal.com/articles/200407/systemDiag.jpg" alt="System diagram" border="1" height="360" width="450" /></p>
<p>We have four main PHP modules (or &#8220;classes&#8221;) that will be widely used in the system. These are tasked with accessing the database, allowing the user to upload files to the site, reading and writing templates, and logging users in and out. These classes all &#8220;extend&#8221; one parent class called &#8220;systemObject.&#8221;</p>
<p>Think of these four as being independent of one another, yet all inheriting whatever data we put in systemObject. This technique of hierarchy allows us to make changes effecting all four system classes, just by adding or modifying the code in the systemObject parent class. Again, this concept will become clearer when we start coding. In the middle of the diagram are the basic areas of the administration system, and each will need one or more PHP pages to perform the required tasks.</p>
<p>This article requires a basic knowledge of PHP programming, although a number of concepts are explained for those less experienced.</p>
<p>Our CMS will be stored in a number of folders, structured as follows:</p>
<table align="center" border="0" cellpadding="0" cellspacing="0" width="60%">
<tr>
<td colspan="4">
<p align="center"><img src="http://www.intranetjournal.com/articles/200408/black.gif" height="20" width="1" /><br />
<img src="http://www.intranetjournal.com/articles/200408/black.gif" height="1" width="100%" /></td>
</tr>
</table>
<p>You may wish to create these four folders now. We&#8217;re going to start by creating the PHP class which all others will &#8220;extend.&#8221; This will be the root of the administration system, and anything we put in it (such as variables and functions) will trickle down to the other classes.</p>
<p>This root class will be called &#8216;SystemComponent&#8217;. The code follows, and a full explanation is below:</p>
<p class="codeMisc">&lt;?<span class="codekeyword">php</span><br />
<span class="codekeyword">class</span> SystemComponent {</p>
<blockquote>
<p class="codeMisc"><span class="codekeyword">var</span> $settings;</p>
<p class="codeMisc"><span class="codekeyword">function</span> getSettings()     {</p>
<blockquote>
<p class="codeMisc"><span class="codeComment">// System variables</span><br />
$settings[<span class="codeVar">'siteDir'</span>] = <span class="codeVar">&#8216;/path/to/your/intranet/&#8217;</span>;</p>
<p class="codeMisc"> <span class="codeComment">// Database variables</span><br />
$settings[<span class="codeVar">'dbhost'</span>] = <span class="codeVar">&#8216;hostname&#8217;</span>;<br />
$settings[<span class="codeVar">'dbusername'</span>] = <span class="codeVar">&#8216;dbuser&#8217;</span>;<br />
$settings[<span class="codeVar">'dbpassword'</span>] = <span class="codeVar">&#8216;dbpass&#8217;</span>;<br />
$settings[<span class="codeVar">'dbname'</span>] = <span class="codeVar">&#8216;mydb&#8217;</span>;</p>
<p class="codeMisc"><span class="codekeyword">return</span> $settings;</p>
</blockquote>
<p class="codeMisc">}</p>
</blockquote>
<p><span class="codeMisc">}<br />
?&gt;</span> <strong>Reminder:</strong> A class is a block of code. Whenever we need to run that code, we create an &#8216;object&#8217; or &#8216;instance&#8217; of the class. We can create as many instances of a class as we like. If you don&#8217;t understand objects and classes by the end of this article, I recommend getting a book or finding a Web site on Object Oriented Programming.</p>
<p>The above code starts off by telling PHP that our class will be called &#8216;SystemComponent&#8217;. Between the braces (squiggly brackets) we declare the variable $settings, and a function called &#8216;getSettings&#8217;. The purpose of this is to store a number of values in $settings, containing the path on the server to the intranet (&#8216;siteDir&#8217;), and the details of the database. Change these appropriately for the database system you&#8217;ll be using (this tutorial uses MySQL, more details coming up). Finally, the &#8216;return&#8217; command sends $settings to whichever class or function has requested it. We&#8217;ll be storing more data in $settings as the series progresses.</p>
<p>Save this code to a file called SystemComponent.php in the &#8216;includes&#8217; folder you created. Now let&#8217;s do something with this class.</p>
<p>All of the information     to be displayed in our Content Management System will be stored in a database.     It is sensible, therefore, to create a reusable PHP class that we can call     upon whenever we need to access our data. The code listed here is for connecting     to a MySQL database. If you&#8217;ll be using a different  system, such as     PostgreSQL, MS SQL or  SQLite, then change the code appropriately.     It&#8217;s obviously quite a bit longer than our previous class, but it performs     a number of very important tasks. The code follows:</p>
<p class="codeMisc">&lt;?<span class="codekeyword">php</span><br />
<span class="codeComment">////////////////////////////////////////////////////////////////////////////////////////<br />
// Class: DbConnector<br />
// Purpose: Connect to a database, MySQL version<br />
///////////////////////////////////////////////////////////////////////////////////////</span><br />
<span class="codekeyword">require_once</span> &#8216;SystemComponent.php&#8217;;</p>
<p class="codeMisc"><span class="codekeyword">class</span> DbConnector <span class="codekeyword">extends</span> SystemComponent   {</p>
<blockquote>
<p class="codeMisc"> <span class="codekeyword">var</span> $theQuery;<br />
<span class="codekeyword">var</span> $link;</p>
<p class="codeMisc"><span class="codeComment">//*** Function: DbConnector,       Purpose: Connect to the database ***<br />
</span><span class="codekeyword">function</span> DbConnector(){</p>
<blockquote>
<p class="codeMisc"> <span class="codeComment">// Load settings from parent         class</span><br />
$settings = SystemComponent::getSettings();<br />
<span class="codeComment"><br />
// Get the main settings from the array we just loaded</span><br />
$host = $settings['dbhost'];<br />
$db = $settings['dbname'];<br />
$user = $settings['dbusername'];<br />
$pass = $settings['dbpassword'];</p>
<p><span class="codeComment">// Connect to the database</span><br />
$this-&gt;link = <span class="codekeyword">mysql_connect</span>($host,       $user, $pass);<br />
<span class="codekeyword">mysql_select_db</span>($db);<br />
<span class="codekeyword">register_shutdown_function</span>(<span class="codekeyword">array</span>(&amp;$this,       &#8216;close&#8217;));</p></blockquote>
<p class="codeMisc">}</p>
<p class="codeMisc"> <span class="codeComment">//*** Function: query, Purpose:       Execute a database query ***<br />
</span> function <span class="codekeyword">query</span>($query) {</p>
<blockquote>
<p class="codeMisc"> $this-&gt;theQuery = $query;<br />
<span class="codekeyword">return</span> <span class="codekeyword">mysql_query</span>($query,       $this-&gt;link);</p></blockquote>
<p class="codeMisc">}</p>
<p class="codeMisc"> <span class="codeComment">//*** Function: fetchArray,       Purpose: Get array of query results ***</span><br />
<span class="codekeyword">function</span> fetchArray($result) {</p>
<blockquote>
<p class="codeMisc"><span class="codekeyword">return</span> <span class="codekeyword">mysql_fetch_array</span>($result);</p>
</blockquote>
<p class="codeMisc">}</p>
<p class="codeMisc"> <span class="codeComment">//*** Function: close, Purpose:       Close the connection ***</span><br />
<span class="codekeyword">function</span> close() {</p>
<blockquote>
<p class="codeMisc"><span class="codekeyword">mysql_close</span>($this-&gt;link);</p>
</blockquote>
<p class="codeMisc">}</p>
</blockquote>
<p><span class="codeMisc"><br />
}<br />
?&gt;</span></p>
<p>Some explanation      is required. After we&#8217;ve named the class &#8216;DbConnector&#8217;, we state     &#8216;extends SystemComponent&#8217;. This tells PHP to grab all of the data and functions     from     SystemComponent, and provide us with access to them (we&#8217;ll need this in order     to get the $settings variable we created earlier).</p>
<p>The first function,     &#8216;DbConnector&#8217;, has the same name as the class that contains it,  meaning     it&#8217;s run automatically when DbConnector loads. It firstly calls the &#8216;getSettings&#8217;     function we wrote     earlier, and extracts from it the various database settings.     It     then     uses     these settings to     connect     to the     database. (Note that we have no code to deal with errors, this will be covered     in detail next time.)</p>
<p>The other functions     are explained below:</p>
<table align="center" border="0" cellpadding="3" cellspacing="0" width="70%">
<tr align="center" bgcolor="#ebebeb">
<td width="33%"><strong>Function</strong></td>
<td><strong>Purpose</strong></td>
</tr>
</table>
<p>Save the above     code (also attached at the bottom of this article) to the &#8216;includes&#8217; folder,     with the name DbConnector.php. This class will be widely used in the Intranet     system, so     let me give you an example     of how     we&#8217;d create an instance of DbConnector,  extract     some data, and display it to the user. Let&#8217;s imagine that our database stores     the details     of one     customer,     and     we want to get hold of his / her name and display it. Here&#8217;s the code:</p>
<p class="codeMisc">&lt;?<span class="codekeyword">php</span></p>
<p class="codeMisc"><span class="codeComment">// Get the PHP file containing the DbConnector class</span><br />
<span class="codekeyword">require_once</span>(&#8216;DbConnector.php&#8217;);</p>
<p class="codeMisc"><span class="codeComment">// Create an instance of DbConnector</span><br />
$connector = <span class="codekeyword">new</span> DbConnector();</p>
<p class="codeMisc"><span class="codeComment">// Use the query function of DbConnector to run a database   query</span><br />
<span class="codeComment">// (The arrow -&gt; is used to access a function of an object)</span><br />
$result = $connector-&gt;query(&#8216;SELECT firstname   FROM customers&#8217;);</p>
<p class="codeMisc"><span class="codeComment">// Get the result</span><br />
$row = $connector-&gt;fetchArray($result);</p>
<p class="codeMisc"><span class="codeComment">// Show it to the user</span><br />
<span class="codekeyword">echo</span> $row['firstname'];</p>
<p class="codeMisc">?&gt;</p>
<p>If you&#8217;d     like to try out the DbConnector class now, you&#8217;ll need to save the above     code in the includes folder in a php file, and set up a &#8216;customers&#8217; table     in your database. I&#8217;ll be covering the set up of our Intranet&#8217;s database     next time.</p>
<p>The importance     and power of using a database is clear &#8211; we can store information in a formal     way, and rapidly access, manipulate and change it. The information we extract     or store is specified using the &#8216;query&#8217; function of the DbConnector     class, and we create instances of DbConnector using the &#8216;new&#8217; command, as     shown above. This also demonstrates the usefulness of     classes &#8211; if the settings are changed in SystemComponent, then all of the     classes that extend it will automatically be changed.</p>
<p><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><strong>Creating       the Database</strong></font></font></font></p>
<p><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">The first table     we&#8217;re going to add to our database will store articles, for display on the     Intranet. The ability to share information is the most important function     of an Intranet, and the job of the Content Management System is to make doing     this as easy as possible. Consider your own data requirements, a few important     ones spring to mind for most articles tables:</font></font></font></p>
<table align="center" border="0" cellpadding="2" cellspacing="0" width="54%">
<tr>
<td bgcolor="#cccccc" width="13%"><strong><font face="Verdana, Arial, Helvetica, sans-serif" size="2"> Field</font></strong></td>
<td bgcolor="#cccccc" width="71%"><strong><font face="Verdana, Arial, Helvetica, sans-serif" size="2"> Purpose</font></strong></td>
<td bgcolor="#cccccc" width="16%"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><strong>Type</strong></font></td>
</tr>
<tr>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"> </font></td>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"> </font></td>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"> </font></td>
</tr>
<tr>
<td bgcolor="#e0e0e0" valign="top"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">ID</font></td>
<td bgcolor="#e0e0e0"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">A         unique number given to each article, and the primary key of the table.</font></td>
<td bgcolor="#e0e0e0" valign="top"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Integer</font></td>
</tr>
<tr>
<td bgcolor="#eeeeee" valign="top"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Title</font></td>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">The         title of the article</font></td>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Varchar(300)</font></td>
</tr>
<tr>
<td bgcolor="#e0e0e0" valign="top"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Tagline</font></td>
<td bgcolor="#e0e0e0"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">A         very short summary of the article</font></td>
<td bgcolor="#e0e0e0"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Varchar(600)</font></td>
</tr>
<tr>
<td bgcolor="#eeeeee" valign="top"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Section</font></td>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">The         category to which the article belongs</font></td>
<td bgcolor="#eeeeee"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Integer</font></td>
</tr>
<tr>
<td bgcolor="#e0e0e0" valign="top"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">TheArticle</font></td>
<td bgcolor="#e0e0e0"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">The         article itself</font></td>
<td bgcolor="#e0e0e0"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Text</font></td>
</tr>
</table>
<p><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Before we can     create the system itself, we need to create the database to store our information.     The code below will set this up if you&#8217;re using the MySQL database system     &#8211; uses of other systems should modify the commands appropriately. Copy and     paste the following into the MySQL admin tool, or use one of the many free     &#8216;client&#8217; programs available:</font></font></font></p>
<p class="codeMisc"><span class="codekeyword"><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2">CREATE TABLE</font></font></span><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"> `<span class="codeVar">databasename</span>`.`<span class="codeVar">cmsarticles</span>`   (<br />
`ID` int(6) <span class="codekeyword">unsigned NOT NULL auto_increment</span> <span class="codekeyword">COMMENT</span> &#8216;The   unique ID of the article&#8217;,<br />
`title` varchar(200) <span class="codekeyword">NULL COMMENT</span> &#8216;The article   title&#8217;,<br />
`tagline` varchar(255) <span class="codekeyword">NULL COMMENT</span> &#8216;Short   summary of the article&#8217;,<br />
`section` int(4) <span class="codekeyword">NULL DEFAULT</span> 0 <span class="codekeyword">COMMENT</span> &#8216;The   section of the article&#8217;,<br />
`thearticle` text <span class="codekeyword">NULL COMMENT</span> &#8216;The article   itself&#8217;,<br />
<span class="codekeyword">PRIMARY KEY</span> (`ID`)<br />
);</font></font></p>
<p><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">If all has gone     to plan, you should now have a working table in the database. We&#8217;re now going     to create a page to allow you or your staff to enter articles into the system.</font></font></font></p>
<p><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"><strong><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Creating       the editor</font></strong></font></font></p>
<p><font face="Arial,Helvetica" size="-2"><font face="Arial, Helvetica" size="2"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Firstly, design     a form using the HTML editor of your choice. Create text fields for each     database field (excluding ID). An example is below:</font></font></font></p>
<table align="center" border="1" cellpadding="0" cellspacing="0" width="80%">
<tr>
<td>
<form name="form1" method="post" action="#"> Title:Tagline:Section:Article:           <textarea name="thearticle" cols="50" rows="6"></textarea> </form>
</td>
</tr>
</table>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/4/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/4/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/4/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=4&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/10/12/creating-a-php-based-content-management-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>

		<media:content url="http://www.intranetjournal.com/articles/200407/systemDiag.jpg" medium="image">
			<media:title type="html">System diagram</media:title>
		</media:content>

		<media:content url="http://www.intranetjournal.com/articles/200408/black.gif" medium="image" />

		<media:content url="http://www.intranetjournal.com/articles/200408/black.gif" medium="image" />
	</item>
		<item>
		<title>Custom Content Management with PHP</title>
		<link>http://khl2007.wordpress.com/2007/10/12/custom-content-management-with-php/</link>
		<comments>http://khl2007.wordpress.com/2007/10/12/custom-content-management-with-php/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 21:12:54 +0000</pubDate>
		<dc:creator>khl2007</dc:creator>
				<category><![CDATA[php articles]]></category>

		<guid isPermaLink="false">http://khl2007.wordpress.com/2007/10/12/custom-content-management-with-php/</guid>
		<description><![CDATA[ Custom Content Management with PHP by Thomas Perl It is well known that you can create powerful Web pages with PHP. Often, the question arises: How are these pages made? This tutorial wants to give you some hints on how to make your Web site appear more managed from both inside and outside. These are [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=3&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://freshmeat.net/articles/view/1291/#top"><img src="http://images.freshmeat.net/img/icon.gif" align="left" border="0" height="25" width="25" /></a>  <strong><font size="+1">Custom Content Management with PHP</font></strong><br />
<font color="#999999">by <a href="http://freshmeat.net/%7Ethp/">Thomas Perl</a></font></p>
<p>It is well known that you can create powerful Web pages with PHP. Often, the question arises: How are these pages made?  This tutorial wants to give you some hints on how to make your Web site appear more managed from both inside and outside.  These are my own approaches to Web development; I hope you find them useful. Take these things as ideas rather than good practice.</p>
<hr align="center" noshade="noshade" size="1" width="100%" />                    <strong>Copyright notice:</strong> All reader-contributed material on freshmeat.net            is the property and responsibility of its author; for reprint rights, please contact the author           directly.<br />
<hr align="center" noshade="noshade" size="1" width="100%" />
<h2>About the hints</h2>
<p>Each hint in this tutorial can be implemented by itself without the others, but sometimes, it&#8217;s more useful if you combine them. It depends on you to decide which hint is good for <strong>your</strong> site.</p>
<h2>Clean directory structure</h2>
<p>Are you tired of calling a subpage of your site <code>http://www.example.com/index.php?page=news&amp;id=45</code>?  You could have a stylish URI in the form of <code>http://www.example.com/news/45/</code>. This gives better-sounding addresses, and your visitors may more easily remember your URIs. All you need is the <strong>Apache</strong> Web server or a browser in which this <code>.htaccess</code> file will be processed in the same way:</p>
<pre>RewriteEngine  on
RewriteBase    /news/
RewriteRule    ^.*$    handler.php</pre>
<p>These three lines instruct <strong>Apache</strong> to rewrite all  URIs from the base directory <code>/news/</code> matching  the rule <code>^.*$</code> to the <code>handler.php</code>  script.</p>
<p>Place this file in your newly-created <code>/news/</code> directory, then create a <code>handler.php</code> file, which will handle all the requests beneath the <code>/news/</code> tree. In other words, all URLs you request within that directory will be handled by <code>handler.php</code>. To get an array of &#8220;parameters&#8221; that are passed to <code>handler.php</code>, you can use this function:</p>
<pre>function get_url_params( $base_url)
{
  $request = substr( $_SERVER['REQUEST_URI'], strlen( $base_url));

  if( substr( $request, -1) == '/')
    $request = substr( $request, 0, -1);

  return explode( '/', $request);
}</pre>
<p>Use it in <code>handler.php</code> like the following:</p>
<pre>get_url_params( '/news/');</pre>
<p>You will receive an array with the parameters, which you can process as you wish. You could improve the <code>get_url_params()</code> function by adding code for processing a <code>?</code> (and everything behind it) in the request URI.</p>
<p>I use this technique to get some fancy URI mapping of my Web site.  It&#8217;s not any harder than using a single <code>index.php</code> which handles all requests, and the benefits are clearly visible. You will be able to make URLs on your Web page that don&#8217;t have to change, which is exactly what <a href="http://www.w3.org/Provider/Style/URI.html">Cool URIs don&#8217;t change</a> tells you is good practice.  (This document got me into making this URI mapping system for my Web site; it&#8217;s really worth reading.)</p>
<h2>Creating a template framework</h2>
<p>You can use templates for outputting both static and dynamic content. You will want to create a directory in which you put the templates. You should secure this directory using this <code>.htaccess</code> file:</p>
<pre>allow from none
deny from all</pre>
<p>This will instruct <strong>Apache</strong> to deny all access to the template files directly.  Access using template functions is still granted, because they&#8217;re not directly accessed.</p>
<p>You will now want to write a template function.  Here&#8217;s what I currently use for my site:</p>
<pre>function template_create( $template_name, $mapping = NULL)
{
  $template_data = file_get_contents( $_SERVER['DOCUMENT_ROOT'] .
    '/templates/' . $template_name . '.template');

  if( NULL != $mapping)
    return str_replace( $mapping['from'], $mapping['to'], $template_data);
  else
    return $template_data;
}</pre>
<p>This means I have my templates in the <code>/templates/</code> directory of my document root and that the files have the extension <code>*.template</code> (which isn&#8217;t necessary; you could name the extension of your templates as you like).  If you include the <code>$mapping</code> parameter, this should be an array with two elements: <code>$mapping['from']</code> and <code>$mapping['to']</code>. All occurrences of the &#8220;from&#8221; element will be replaced with the &#8220;to&#8221; element. Both elements can also be arrays, which results in all elements in the &#8220;from&#8221; array being replaced with the corresponding elements in the &#8220;to&#8221; array.  Here is an example of how you could use this:</p>
<pre>$time = time();
$text = 'This is a Test';

$mymap = array(
  'from' =&gt; array( '%%TIME%%', '%%TEXT%%'),
  'to' =&gt; array( $time, $text)
);

template_create( 'my_document', $mymap);</pre>
<p>Where the file <code>/templates/my_document.template</code> could look like this:</p>
<pre>&lt;p&gt;Hello. The time is %%TIME%% and here is some text:&lt;/p&gt;
&lt;p&gt;%%TEXT%%&lt;/p&gt;</pre>
<p>You should now have seen how easy it is to create templates for pages and how to fill them with dynamic content. This is especially useful if you want to create templates for displaying dynamic data from databases and such. You can surely improve this by creating a function which reads one row from a database table and fills a mapping variable with data from that row, returning a valid mapping for the <code>template_create()</code> function.</p>
<h2>Using templates for a unique layout</h2>
<p>This is a short and easy one. Let&#8217;s say you want to create a unique layout for a page, but you don&#8217;t want to include the full code in every file or script you write. Use the templates hint above to create template functionality and include it in every subpage.  Then, use it like the following (assuming <code>header.template</code> and <code>footer.template</code> include all the code for the beginning and the ending of the page):</p>
<pre>template_create( 'header');

<em>// place content output here</em>

template_create( 'footer');</pre>
<p>Yes, that&#8217;s all!</p>
<h2>Make database access abstract</h2>
<p>Here&#8217;s some more code for your include directory.  After some time, it&#8217;s easier to make queries in this fashion than to make a <code>mysql_query</code> everywhere you need some data from the database.  It also gives more sense to the code and makes it more readable because you just see the function call with the important parameters.</p>
<pre>function database_get_single_element( $table_name, $key, $value);
function database_select_multiple_elements( $table_name, $from, $to,
   $order = NULL, $how = 'ASC', $key = NULL, $value = NULL);
function database_get_random_element( $table_name, $key = NULL, $value = NULL);
function database_get_column_sum( $table_name, $column, $key = NULL, $value = NULL);
function database_get_next_element( $query);
function database_count_elements( $table_name, $key = NULL, $value = NULL);</pre>
<p>The <code>database_get_single_element()</code> function will select and <code>mysql_fetch_assoc</code> <em>one</em> row of the table named by <code>$table_name</code>.  There will also be a <code>WHERE</code> part, and the <code>$key</code> field in the table must have the <code>$value</code> value.</p>
<p>The <code>database_select_multiple_elements()</code> will return a <code>mysql_query</code> of the same things. <code>$from</code> and <code>$to</code> are for the <code>LIMIT</code> part of the query.  The data can then be fetched with <code>database_get_next_element()</code>, which is exactly the same as <code>mysql_fetch_assoc</code>, but has a more informative name.</p>
<p><code>database_get_random_element()</code> will use the <code>ORDER BY RAND() LIMIT 1</code> SQL query words to select some random element from the table.</p>
<p>Finally, <code>database_count_elements()</code> counts the number of rows of the results.  This is good for counting how many elements another query will return.</p>
<p>These are just some hints of what I mean by database abstraction.  I&#8217;m sure that you&#8217;ll probably need other functions which better suit your needs, and you might not need all the functions I&#8217;ve shown.  Let me tell you from experience that it will get a lot easier when you start using these functions instead of simple queries. And if you have some very complicated queries, make a function for each of them. If your database layout changes or if you use another database instead of MySQL (which is certainly possible in PHP), you do not have to change all queries, but simply fire up your editor on the database include files and change all queries there.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/khl2007.wordpress.com/3/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/khl2007.wordpress.com/3/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/khl2007.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/khl2007.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/khl2007.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/khl2007.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/khl2007.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/khl2007.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/khl2007.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/khl2007.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=khl2007.wordpress.com&amp;blog=1553466&amp;post=3&amp;subd=khl2007&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://khl2007.wordpress.com/2007/10/12/custom-content-management-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a5009f867927240bf1e49026dbf9e490?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">khl2007</media:title>
		</media:content>

		<media:content url="http://images.freshmeat.net/img/icon.gif" medium="image" />
	</item>
	</channel>
</rss>
