Tutorials Books Videos Forums

Change the theme! Search!
Rambo ftw!

Customize Theme


Color

Background


Done

XML Guestbook with PHP

by Arjen Gosman aka Flashmatazz   | filed under Web, HTML, CSS, and XML

This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.

So you want to create a guestbook but you don't have a database like MySQL at your disposal? Then this tutorial might come in handy. The things you'll need are Flash, a PHP script and the XML file that will hold your data.

Here's how the guestbook will look like:

[ the XML guestbook in action ]

Setting up the Flash movie

Let's start by creating a new Flash movie. Or, alternatively, you could just read through the tutorial and download the ZIP file at the end ;)
Below I've described how the movie is setup exactly:

  1. On the main stage create e dynamic textfield with instancename myGuestbook which will hold all our text. In this textfield's properties, make sure it's a multiline textfield and that the Render text as HTML option is active.
  2. Drag the scrollbar component onto this textfield, or create your own custom scroller.
  3. Create a dynamic textfield with instancename myCount which is used to show the total amount of messages in our guestbook.
  4. Create an "Add a message" button with instancename createButton.
  5. Still on the main stage, create 2 buttons with instancenames previous and next which are used to walk through all pages of our guestbook.
  6. Create a dynamic textfield with instancename nowShowing.
  7. Create 2 buttons with instancenames previous and next.
  8. Create a movieclip with instancename createMessage.
  9. Inside this movieclip, create two input textfields: nameField and messageField.
  10. Also within this mc, create two buttons: closeButton and sendButton.
  11. Finally, still within this mc create a dynamic textField called errorField.

Now that we have all the elements we need, we can go and spice it up a bit with some actionscript. Let's continue to the next section.

Actionscript

First you will have to get a basic understanding on how to handle XML data within Flash. Senocular has written some great tutorials on this subject, which you can find in the Actionscript tutorials section.

If you feel like you're ready for it already, then take a look at the following actionscript. This needs to go into the first frame of the flash movie:

var currPage = 0;
var showAmount = 10; // set this to the amount of entries you want to view at a time
previous._visible = false;
createMessage._visible = false;
createButton.onRelease = function(){
  this._visible = false;
  this._parent.createMessage._visible = true;
  if (createMessage.nameField.text == ""){
  Selection.setFocus(createMessage.nameField);
  }
  else if (createMessage.messageField.text == ""){
  Selection.setFocus(createMessage.messageField);
  }
}
// **** Load XML ****************************
myXML = new XML();
myXML.ignoreWhite = true;
receiverXML = new XML();
myXML.onLoad = function(success){
  myXML.contentType = "text/xml";
  if (success){
  this.showXML();
  }
  else{
  trace("Error loading XML file");
  }
}
myIdentifier=Math.round(Math.random()*10000);
myXML.load("guestbook.xml?uniq="+myIdentifier);
receiverXML.onLoad = function(){
  this.contentType = "text/xml";
  _root.currPage = 0;
  this.showXML();
}
createMessage.closeButton.onRelease = function(){
  this._parent._visible = false;
  createButton._visible = true;
}
createMessage.sendButton.onRelease = function(){
  var myName = this._parent.nameField.text;
  var myMessage = this._parent.messageField.text;
  if (myName == ""){
  this._parent.errorField.text = "please fill out your name";
  Selection.setFocus(this._parent.nameField);
  }
  else if (myMessage == ""){
  this._parent.errorField.text = "please leave a message";
  Selection.setFocus(this._parent.messageField);
  }
  else {
  myXML.firstChild.appendChild(myXML.createElement("entry"));
  myXML.firstChild.lastChild.attributes.myName = myName;
  myXML.firstChild.lastChild.appendChild(myXML.createElement("myText"));
  myXML.firstChild.lastChild.lastChild.appendChild(myXML.createTextNode(myMessage));
  myXML.sendAndLoad("processXML.php", receiverXML);
  this._parent._visible = false;
  createButton._visible = true;
  }
}
XML.prototype.showXML = function(){
  myGuestbook.scroll = 1;
  myGuestbook.htmlText = "";
  var numItems = this.firstChild.childNodes.length;
  var firstItem = numItems - (currPage*showAmount);
  if (currPage == 0) previous._visible = false;
  var lastItem = firstItem - showAmount ;
  if (lastItem<=0) {
  lastItem = 0;
  next._visible = false;
  }
  myCount.text = "Total messages: " + numItems;
  if (firstItem == lastItem+1) nowShowing.text = "Showing message " + firstItem;
  else nowShowing.text = "Showing message " + firstItem + " to " + (lastItem + 1);
  for (i=(firstItem-1); i>= lastItem; i--){
  myGuestbook.htmlText += "<B>" + this.firstChild.childNodes[i].attributes.myName + "</B> wrote:\n";
  myGuestbook.htmlText += this.firstChild.childNodes[i].firstChild.firstChild.nodeValue + "\n\n";
  }
}
previous.onRelease = function(){
  currPage--;
  myXML.showXML();
  next._visible = true;
}
next.onRelease = function(){
  currPage++;
  myXML.showXML();
  previous._visible = true;
}

Are you still here? I didn't scare you away now did I? Alright, onto the next section then because I owe you a bit of an explanation.

Actionscript explained

I'm not going to explain every singe line of actionscript, beause a lot of it speaks for itself. Instead, I'm going to focus on the main functionality of the guestbook, namely the XML.sendAndLoad() function which has the following usage (taken from the Flash Actionscript dictionary):

myXML.sendAndLoad(url,targetXMLobject)

This method encodes the specified XML object into a XML document, sends it to the specified URL using the POST method, downloads the server's response and then loads it into the targetXMLobject specified in the parameters. The server response is loaded in the same manner used by the load method.

Now what does this mean exactly? Obviously it means that we need two XML objects in our script: the object that is sent to the specified URL - which in our case is a PHP script - and a target object that receives data back from this PHP script. The following lines create those two XML objects:

myXML = new XML();
myXML.ignoreWhite = true;
receiverXML = new XML();

Our guestbook.xml file initially is loaded into the myXML object. After it has been successfully loaded the showXML() prototype is called:

if (success){
  this.showXML();
}

This prototype fills our main textfield with the data from the XML file, starting with the last entry that has been added to the guestbook. It only shows the number of entries that are defined in the variable showAmount, defined in line 2, which in our case equals 10:

var showAmount = 10;

We also want to keep track of the number of pages we need for all of our guestbook entries. Let's say we have 12 entries and only want to show 10 per page. Obviously our entries should then be divided over 2 pages. The currPage variable is used for this, together with the firstItem and lastItem variables. The first item we'd like to see is entry #12, the entry that was last added to the guestbook. So:

var firstItem = numItems - (currPage*showAmount);

and because currPage initially equals 0 (the first page) this gives us:

var firstItem = 12 - (0*10); // equals 12

the last item shown on this page should then ofcourse be 12 minus 10 = 2 which is done by:

var lastItem = firstItem - showAmount ;

Further, we don't want the previous button to be visible when we're already viewing the first page so therefore:

if (currPage == 0) previous._visible = false;

Now, if we press the next button, the currPage variable is increased by 1. After this, the showXML() function is called again. Now firstItem will equal 2:

var firstItem = 12 - (1*10); // equals 2

Subsequently, lastItem will equal 2 - 10 = -8. Obviously, in such a case where the previous section would not contain the amount of entries as defined in the showAmount variable, if we would only write:

var lastItem = firstItem - showAmount ;

we'll end up with a negative value for lastItem which would mess up the for-loop that fills our textfield. Therefore we also need the following, which sets lastItem to 0 and also hides the 'next' button when viewing the previous section.

if (lastItem<=0) {
  lastItem = 0;
  next._visible = false;
}

Having said all this, I think it will be quite clear what the previous.onRelease and next.onRelease event handlers do.

Intermezzo: the XML file

So how exactly is the XML file setup? We start out with an 'empty' file, meaning that there are no guestbook entries yet. The file looks like this:

<?xml version="1.0"?>

  <guestbook>

  </guestbook> 

Actionscript continued

Now that we know how the XML file is setup and how the showXML() function works we come to the part where we want to add a message to our guestbook. By clicking the "add a message" button, the createMessage movieclip becomes visible. After filling out the name and message fields and clicking the send button, the following happens:

  1. The values from the two input textfields are assigned to the variables myName and myMessage:
    var myName = this._parent.nameField.text;
    var myMessage = this._parent.messageField.text;
  2. The code checks if both textfields are actually filled out. If one of them is left blank an errormessage is shown in the errorField and the cursor is placed inside the empty textfield.
    if (myName == ""){
      this._parent.errorField.text = "please fill out your name";
      Selection.setFocus(this._parent.nameField);
    }
    else if (myMessage == ""){
      this._parent.errorField.text = "please leave a message";
      Selection.setFocus(this._parent.messageField);
    }
  3. If both fields are filled out (the else statement), a new <entry> node is added to the myXML object. Note that this node is added to myXML's firstchild, which is the <guestbook> node:
    myXML.firstChild.appendChild(myXML.createElement("entry"));
    The myXML object now looks like this:
    <?xml version="1.0"?>
    
      <guestbook>
    
      <entry>
    
      </entry>
    
      </guestbook> 
  4. After that, a myName attribute is added to this new <entry> node and assigned the value of the myName input textfield:
    myXML.firstChild.lastChild.attributes.myName = myName;
    Resulting in:
    <?xml version="1.0"?>
    
      <guestbook>
    
      <entry myName="Flashmatazz">
    
      </entry>
    
      </guestbook> 
  5. Then a new <myText> node is created as a childnode of the newly created <entry> node:
    myXML.firstChild.lastChild.appendChild(myXML.createElement("myText"));
    Giving us the following:
    <?xml version="1.0"?>
    
      <guestbook>
    
      <entry myName="Flashmatazz">
    
      <myText> </myText>
    
      </entry>
    
      </guestbook> 
  6. A new text node, containing the value of the myMessage input textfield is added to this newly created <myText> node:
    myXML.firstChild.lastChild.appendChild(myXML.createElement("myText"));
    which finally gives us:
    <?xml version="1.0"?>
    
      <guestbook>
    
      <entry myName="Flashmatazz">
    
      <myText>Here goes the text that the user wrote in the
      message textfield </myText>
    
      </entry>
    
      </guestbook> 
  7. And now, finally, this updated myXML object is sent to the PHP script which resides on the server:
    myXML.sendAndLoad("processXML.php", receiverXML);

Curious about how this PHP script looks like? Read about it in the previous section.

 

        

The PHP script

Now that Flash has sent our updated myXML object to the PHP script on the server, we'll have a look at how this script works. As you could see in the previous section, the script is named processXML.php and here is how it looks:

<?php
$xmlString = $HTTP_RAW_POST_DATA;
if (is_null($xmlString)) {
  print "No data was sent";
}
else {
  $file = fopen("guestbook.xml", "w+") or die("Can't open XML file");
  if(!fwrite($file, $xmlString)){
  print "Error writing to XML-file";
  }
  print $xmlString."\n";
  fclose($file);
}
?>

Explanation:

  1. In the first line, the data that was sent from Flash is retrieved and assigned to the $xmlString variable. Data sent using the XML object is not URL encoded. Therefore PHP won't parse the data into variables and you will need to use $HTTP_RAW_POST_DATA to access the raw data directly. $xmlString now contains one long string where the new guestbook entry is already inserted.
  2. The if statement then uses the is_null() function to check if the $xmlString variable really contains a value. If for some reason the data is not retrieved correctly or the PHP script is called directly from the browser, we could at the end of the script end up with an empty XML file.
  3. In the else statement, if $xmlString does contain data, we use the fopen() function to open the file guestbook.xml using the w+ mode. This mode opens the file for reading and writing, places the file pointer at the beginning of the file and truncates the file to zero length, meaning that all content is erased. If the file does not exist, it will attempt to create it. The result of the fopen() action is assigned to the $file variable, meaning that $file can now be used as a pointer to our XML file. Note that the file must be accessible to PHP, so you need to ensure that the file permissions allow this access. This means that you must set (CHMOD) permissions to 777, which you can do with your FTP program for example.
  4. Within the following if-statement the script attempts to write this 'xml-string' back to our guestbook.xml file.
  5. After that the $xmlString variable is sent back to Flash where it is received in our receiverXML object.
  6. Finally a bit of cleaning up is done to free up the used file descriptor: our XML file is closed using the fclose() method.

And now we're almost done. By sending our data back to Flash, the receiverXML.onLoad handler is invoked. Within this handler the showXML() prototype is called again, just as it was when the flash movie first loaded. This function again loops through our - now updated - XML file and shows all entries in our textfield so we can read what we've just written in the guestbook

This leaves me with one final note taken from Macromedia's Technotes:

Note

Problem

Loading more than 64k of data using the LoadVars.load, loadVariables, XML.load, or XML.sendAndLoad actions can cause poor browser performance. Common problems can include 501errors, "not implemented" errors, or general browser slowness.

Solution

Load the information in smaller packets. Using multiple load actions and spreading the data out over a series of frames can reduce the work the Macromedia Flash Player needs to do to load and parse the information. This can greatly increase browser and loading performance.

 

After done some testing with an XML file exceeding 500 Kb (over 700 entries) I must say I haven't experienced this problem however.
To wrap up this tutorial: although a mySQL database offers a much more powerful way to create a guestbook, it is actually possible to create a simple one using only Flash, PHP and an XML file.

I hope this tutorial has been useful for you. If you have any questions, feel free to post on the forums... but first download the zipped guestbook and give it a go ;)

 

Cheers!

Arjen Gosman aka Flashmatazz
arjengosman.nl

Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence, ads, and algorithm-driven doodads. A huge thank you to all of you who buy kirupa's books, became a paid subscriber, watch the videos, and/or interact on the forums.

Your support keeps this site going! 😇

The KIRUPA Newsletter

Thought provoking content that lives at the intersection of design 🎨, development 🤖, and business 💰 - delivered weekly to over a bazillion subscribers!

SUBSCRIBE NOW

Creating engaging and entertaining content for designers and developers since 1998.

Follow:

Popular

Loose Ends

:: Copyright KIRUPA 2026 //--