Articles: 843 | Categories: 148   
   
   
Home Articles Contact Us
 
 
 
 
XML Guestbook with PHP (0 Comments)
Admin: Posted Date: April 4, 2010

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.

XML Guestbook with PHP
         by Arjen Gosman aka Flashmatazz: 18 april 2004

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.

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 page.

Actionscript
First you will have to get a basic understanding on how to handle XML data within Flash.

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 page 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 last page 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 last page.

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);


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 on the previous page, 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

 

 

 

 

 
 
Add a Comment:
 
(You must be signed in to comment on an article. Not a member? Click here to register)
   
Title:

Comments: