AS Reference  :  Notes Index  :  Resources  :  About/Contact  :  Downloads

Flash MX (Actionscript 1) and PHP: Address Book Example

Communicating with PHP (or any other serverside script) from Flash has gotten much easier with the introduction of the LoadVars object in Flash MX. Here's a sample in which we use a MySQL database (containing friends' email and phone information and a picture and caption if we have one), a PHP script to access that information, and Flash to present it. I'll go through each of the steps I went through to create it.

Setting up the MySQL database and PHP to access it

The first thing to do in any database application is define the structure of the data. In this case, I created a new MySQL table with these fields:

and then populated the field manually with statements like these:

insert into contacts 
values (NULL, 'Anderson', 'Lois', '301-424-5555', 
'lois@yahoo.com', 'lois.jpg', 'Lois, 2001');
(It's a small table; for a larger table, it would make more sense to populate the table by reading in a text file with the information).

To make sure the table is accessible via PHP, I used this sample code to test it:

<?php
mysql_connect("servername","username","password");
mysql_select_db("databasename");

$qr = mysql_query("SELECT * FROM contacts");

$nrows = mysql_num_rows($qr);
for ($i=0; $i < $nrows; $i++) {
  $row = mysql_fetch_array($qr);
  echo $row['lastName'].", ".$row['firstName']."<br>";
  echo "  ".$row['phone']." ".$row['email']."<br>";
  echo "  ".$row['picFile'].": ".$row['caption']."<br><br>";
}
?>

(Here is a nice generically-usable replacement for the last section, which finds and displays all fields in each record, passed on from Joshua Mostafa:)

while ($row = mysql_fetch_assoc ($qr)) {
  $r_string .= '<br>';
  while (list ($key, $val) = each ($row)) {
    $r_string .= $key . '=' . $val . ', ';
  }
}
echo $r_string;

Setting up the Flash movie

To display text in a Flash movie, you need a textfield (or several textfields). You can either create one dynamically, using createTextField, or set one up in the movie, give it an instance name and use that. We chose the latter for this sample. The main textfield has instance name content (you can find it in the "textfield & scrollbar" layer of the fla), and is set to multiline with the "Render text as HTML" option selected, so that we can include links in it.

Adding the scrollbar

Because we are going to put all of the address records for a given letter of the alphabet into one field, we have to make it scrollable, in case there are more entries than fit in the size we allotted. To do that, we open the Components panel and drag a copy of the scrollbar into the textfield. It automatically snaps into place, and is automatically associated with instance "content". Piece of cake.

Set up movieclip to hold jpg

Another thing we need in the movie is something to hold the jpg we're going to load in. To do that, we create a placeholder movieclip (in layer "pic, caption" of the fla) and give it instance name picHolder. In the same layer, we include another textfield (also multiline, but not html) with instance name caption.

Set up tabs as button movieclips

Because all of the tabs have the exact same function but a slightly different appearance, we can use Flash MX's new button movieclip feature to make them. That is, we'll create a template tab that is a movieclip, then copy it for as many tabs as we need, and set up code to put the right letter on the tab and attach the right handler to the tab to make it respond to a mouseclick.

Each tab movieclip contains a textfield "letter". Each tab movieclip will also have an onRelease function assigned to it to tell it what to do when it's clicked. In order to perform the right action, though, we need to know which tab we're accessing. To do that, we name the tab movieclips in a way that allows us to find out which one is currently being clicked. The A tab is given instance name tabA, the B tab tabB, etc. Using that information, this is the code (in frame 1 of the main movie) that sets up our 3 tabs correctly (so that they display the right letter and act correctly when clicked):

for (var i=65; i<=67; i++) {
  // display the correct letter on the tab
  this["tab"+chr(i)].letter.text = chr(i);
  // when this tab is clicked
  this["tab"+chr(i)].onRelease = function() {
    // can't use chr(i) here -- must use mc name
    // because i will not be set when the event actually happens
    c.thisLetter = this._name.substr(3,1);
    bigLetter.text = c.thisLetter;
    content.htmlText = "Loading data for " + c.thisLetter;
    // scope of this function is main timeline so can refer to c directly
    c.sendAndLoad("flashmx_dbPassAndReturnString.php",c,"POST");
  }
}

For each letter A-C, we assign that letter to the "letter" textfield on the tab. Then, also for each letter, we assign a routine that will do the following when the tab is clicked:

Remember, these things are not being done in the main movie; they are being set up as instructions to be carried out *when a tab is clicked*. Now we need to set up the LoadVars object itself, as well as the actions that will be performed when data is returned from our php script

Flash-PHP communication with LoadVars

A LoadVars object is used to transfer data to and/or from a serverside script, such as PHP, ASP, CF, Perl, JSP, from/to a Flash MX movie. Properties of the LoadVars object will be sent to the script as variables, either by the POST or GET method, and any variables returned from the script will be available to Flash as properties of the LoadVars object specified in the load method.

Using LoadVars.send

format = loadVarsObject.send( url, target, method ), where all are strings

In our sample, we want to send the letter of the tab we selected so that the php script can use it to query the database. So a loadVars object must be created and one of its properties set to that letter. Before we look at the code in the sample, here is an example in which a value is assigned to a property of newly created LoadVars object and sent to a php script:

var c = new LoadVars();
c.thisLetter = "A";
c.send("dbquery.php","_self","POST");

The script then reads that property as a POSTed variable and uses it to query the database and display the information found:

<?php
mysql_connect("servername","username","password");
mysql_select_db("dbname");

$qr = mysql_query("SELECT * FROM contacts WHERE LEFT(lastName,1) =
 '".$HTTP_POST_VARS['thisLetter']."'");

// display visitors row (1)
$nrows = mysql_num_rows($qr);
for ($i=0; $i < $nrows; $i++) {
    $row = mysql_fetch_array($qr);
    echo $row['lastName'].", ".$row['firstName']."<br>";
    echo "  ".$row['phone']." ".$row['email']."<br>";
    echo "  ".$row['picFile'].": ".$row['caption']."<br><br>";
}
?>

This is what gets output to the output window (the same window in which the Flash movie was running, since we specified "_self" as the target in our loadVars.send):

Anderson, Lois
301-424-5555 lois@yahoo.com
lois.jpg: Lois, 2001

Armand, Cheryl and Joe
912-948-4444 armandcj@hh.com
babysue.jpg: C and J's baby Sue, 9 days old

(etc)

Because we used POST as a send parameter, we had to read the variables with PHP $HTTP_POST_VARS. If you need to build the query string yourself (which is sometimes the case), you can just send it without specifying a method and it will default to GET because of the appended querystring:

var c = new LoadVars();
c.send("dbquery.php?thisLetter=A","newWindow");
and this in dbquery.php:
<?php
mysql_connect("servername","username","password");
mysql_select_db("dbname");

$qr = mysql_query("SELECT * FROM contacts 
WHERE LEFT(lastName,1) = '".$HTTP_GET_VARS['thisLetter']."'");

// display visitors row (1)
$nrows = mysql_num_rows($qr);
for ($i=0; $i < $nrows; $i++) {
    $row = mysql_fetch_array($qr);
    echo $row['lastName'].", ".$row['firstName']."<br>";
    echo "  ".$row['phone']." ".$row['email']."<br>";
    echo "  ".$row['picFile'].": ".$row['caption']."<br><br>";
}
?>

produces the same output as above, but in a new document window (newWindow). When writing a Flash-to-serverside application, it's a good idea to run simple tests like the above code, using .send to make sure variables passed as expected, before trying to test the whole application.

Receiving using LoadVars.load

format = loadVarsObject.load( url ), where url is an expression

Now we've got variables being sent to the php script and used successfully there, how to get the information returned to Flash? Before we tackle sending and receiving together, let's look at just receiving, with the loadVars object's load method.

Variables sent to Flash from a serverside script must always be sent as a string of var=value's separated by &'s (eg, lastName=Anderson&phone=301-424-5555). If such a string is sent in response to a loadVars load, the variables can then be read in Flash as properties of the loadVars object. But there's one more thing that needs to be taken into consideration. Getting information from a database and sending it back to Flash does not happen instantaneously -- something needs to signal Flash when the operation is complete, so the movie won't try to use the variables before they're available (a very common newbie problem). What needs to be done is to define a function that will be executed when data is returned and assign that function to the onLoad property of the LoadVars object. That says: when variables have been received, execute the function. This can be done in one of two ways: with an anonymous function (also called a function literal, I think):

var c = new LoadVars();
c.onLoad = function() {
  returnvals.text = "returned from php: \n\n";
  for (i in this) {
    returnvals.text += i + " = " + this[i] + "\n";
  }
};
or with a named function, which is then assigned (but not called -- ie, don't put () after the function name) to the onLoad property:
function showValues() {
  returnvals.text = "returned from php: \n\n";
  for (i in this) {
    returnvals.text += i + " = " + this[i] + "\n";
  }
}
	
var c = new LoadVars();
c.onLoad = showValues;

Notice that either way, referring to "this" inside the function is the same as calling the loadVars object by name. So with either piece of code above, followed by this line to actually request the data:

c.load("passvars.php");

and in passvars.php, this:

<?php
$lastName = "Anderson";
$phone = "301-424-5555";
echo "lastName=".$lastName."&phone=".$phone;
?>

we get this output:

returned from php: 

phone = 301-424-5555
lastName = Anderson
onLoad = [type Function]

The two variables we want to receive are phone and lastName. In our example onLoad shows up too, even though it's not a variable, because it's also a property of the loadVars object. But usually, you know what variables you are expecting and will do something only with those variables and ignore any other properties of the loadVars object. You can also delete any superfluous properties before issuing the load (although onLoad is not superfluous and must always be a property of loadVars for it to function correctly).

Sending & receiving at once with LoadVars.sendAndLoad

format = loadVarsObject.sendAndLoad( url, loadVarsObject, method ),
where url and method are expressions and loadVarsObject is not

In our sample, we want to pass the selected letter (of whatever tab is clicked) and pass back all records handed back by the query. So our php routine has to send back a var=value string of all those variables and our Flash movie has to use the right properties of the loadVars object to display them in the scrolling textfield we put in the movie.

The php script returns a string that looks like

"&n=4&lastName0=Anderson&firstName0=Lois&...&caption3=lastyear&"

with values for the four records found with last name starting with A. Notice that we've also added a variable at the beginning of the string to tell Flash how many records to expect, so that we can set up an appropriate loop to read them all. This is what that part of the php script looks like:

$nrows = mysql_num_rows($qr);
$rString = "&n=".$nrows;

for ($i=0; $i < $nrows; $i++) {
  $row = mysql_fetch_array($qr);
  $rString .= "&lastName".$i."=".$row['lastName']. 
    "&firstName".$i."=".$row['firstName'];
  $rString .= "&phone".$i."=".$row['phone']."&email".$i."=".$row['email'];
  $rString .= "&picFile".$i."=".$row['picFile'].
    "&caption".$i."=".$row['caption'];
}
echo $rString."&";

Note: It is a good idea to add a "&" to the beginning of the return string (as in the second line above) and another at the end (as in the last line). Adding it at the end ensures that any extra carriage returns, linefeeds, or other extraneous characters will not be included as part of the final returned variable.

We've seen all of the Flash code to set things up already; now we just have to define the function to execute when the variables are returned (to read and do something with those variables) and then issue the correct sendAndLoad command. Here is that code from the Flash movie :

function showContent() {
  var i;  
  content.htmlText = "";
  for (i=0; i < this.n; i++) {
    if (this["picFile"+i] != "") {
      content.htmlText += 
        "<b>" + this["firstName"+i] + " " + this["lastName"+i] + 
        "</b>" + "<a href='asfunction:showjpg," + this["picFile"+i] + 
        "," + escape(this["caption"+i]) + 
        "'>  (<font color='#0000cc'>pic</font>)
        </a><br>";
    } else {
      content.htmlText += 
        "<b>" + this["firstName"+i] + " " + this["lastName"+i] + 
        "</b><br>";
    }
    content.htmlText += "  " + this["phone"+i] + "<br>";
    content.htmlText += 
    "  <a href='mailto:" + this["email"+i] + "'>" + 
    this["email"+i] + "</a><br><br>";
  }
}

// Create new load vars object c for data transfer
var c = new LoadVars();
c.onLoad = showContent;

and remember that we execute the sendAndLoad itself from within the onRelease routine for the selected tab, with this code:

  this["tab"+chr(i)].onRelease = function() {
    ...
    c.sendAndLoad("flashmx_dbPassAndReturnString.php",c,"POST");
  }

Now we're all set up to send an A, B, or C to the php script and do something with the variables it returns, using the same LoadVars object (c) for both sending and receiving. To make sense of the code in function showContent, you have to remember that these are all equivalent ways of accessing the phone3 property of object c:

  c.phone3

    and
	 
  c["phone"+3]
	
    and
	  
  i=3
  c["phone"+i]
	
    and
	  
  i=3
  this["phone"+i]  if the code is inside a function assigned to c

(For more information on that, see the Arrays and Objects page.)

Thus, we simply take each property that is returned and display it as we wish in the textfield we created.

asfunction

format = asfunction:functionname,param where param is an expression

There are two more interesting things in this sample. One is the use of asfunction to call a function within Flash, the other is loading a jpg directly into Flash. As you can see from the code in showContent above, asfunction allows us to provide an html-like link within a Flash textfield to another Flash routine. In this case, it calls function showjpg and passes a parameter (it can only pass one parameter) which contains both the name of the jpg file and the caption, separated by a #. This is what showjpg looks like:

function showjpg(paramString) {
  // get the individual parameters:
  // params[0] = picture file name
  // params[1] = caption
  var params = paramString.split("#");
  picHolder.loadMovie(params[0]);
  caption.text = unescape(params[1]);
}

The first thing we do is split the passed parameter into the two parameters we really want, using the string split function to produce a 2-element array. The first element now holds the jpg name, the second holds the caption.

Loading a jpg

format = mcInstanceName.loadMovie(jpgfile) where jpgfile is an expression

The line

picHolder.loadMovie(params[0]);
says load the image specified by the filename stored in params[0] into the picHolder movieclip. Because picHolder was created with an upper left registration point (0,0), and we sized all the photos to match its size, the photo loads into exactly the right place and we needn't do anything more with it. After we load the jpg into its holder, we fill in the caption with the passed caption text. The unescape function is used to un-urlencode the value (notice that we used the escape function to urlencode the value before sending it -- otherwise characters in the caption like ":" and "," would not show up correctly).

Note that if the pictures are saved in another folder, eg in folder pictures under the one with the html page embedding the swf, the line above would be

picHolder.loadMovie("pictures/" + params[0]);

And that's it. LoadVars object to send data, php script to use it and send data back, showContents function to deal with the data once it's received by Flash.

Intro
Flash: What & How
Example Sites
Create
Draw, Edit Shapes
Gradients
More Drawing Tips
Import
A Sample
Animate
Frames, Keyframes
Motion Tweens
More Motion Tweens
Shape Tweens
Masks
Control
Stop/Replay
Movieclips Intro
Movieclip Reference
Site Structure 1
Slideshow Movieclip
Contact Form
Scroll Resume
Preloader
Site Structure 2
Publish
Display Options
Player Detection
Optimize
AS 2.0 Basics
Intro to Syntax
Playhead Commands
Playhead Cmds 2
Coded Tween
onEnterFrame
Intro to Classes
Declare/Assign
Comments, Trace
Simple Data Types
Arrays & Objects
Code Blocks
Operators
Beyond Buttons
Code Structure
Toggle Controls
Group of Buttons
Drag and Hit
Distort Magnifier
Scroll Text
Bee Game
Dart Shooter
Sound Control
Easing Slider
Easing Slider 2
Components Intro
Timers & Delays
Dynamic Content
Intro
Drawing API
Create Text
Attach Movieclips
Easing Slider 3
Easing Slider 4
Load jpg/swf
Sliding Viewer
Preload swf
XML
Easing Slider 5
Server Comm
LoadVars (w/ PHP)
AS - PHP Lookup
Text File
Database 1:LoadVars
Database 2:Remoting
Read from directory
AS 2.0 Classes
Intro
Math
Key
Date
Color
EventDispatcher
New Samples
Pie Chart
Event-model Emailer
Tween Sequence
Fuse Sequence
SVG in Flash
Bitmap Topo
SWF as Data Holder
Two-level Menu
Yahoo! Flash Maps
Class-based Game
ASTB Samples
Disclaimer
3D Outlines
Bounce Collide
Address Book
Save Drawings
Home  :  Notes Index  :  Resources  :  About/Contact  :  Downloads